This is an automated email from the ASF dual-hosted git repository.
bamaer pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new 01304c4a92 Issue #8942 : Don't mark generated SQL as changed (#8944)
01304c4a92 is described below
commit 01304c4a92dd37f15237c1a4c4d0b792e2d8c346
Author: Matt Casters <[email protected]>
AuthorDate: Thu Oct 15 19:38:05 2026 +0200
Issue #8942 : Don't mark generated SQL as changed (#8944)
Generated DDL and suggested queries open in the database SQL editor with
the changed flag clear. The caret is placed on the last line of the script
instead of in the tree filter.
---
.../perspective/database/DatabaseSqlEditorTab.java | 29 +++++++++++++
.../perspective/database/DatabaseWorkbench.java | 49 ++++++++++++++++++++--
.../database/DatabaseSqlEditorTabTest.java | 12 ++++++
3 files changed, 86 insertions(+), 4 deletions(-)
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseSqlEditorTab.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseSqlEditorTab.java
index 1e5c154952..cdf523cf2d 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseSqlEditorTab.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseSqlEditorTab.java
@@ -156,6 +156,35 @@ public class DatabaseSqlEditorTab implements
IHopFileTypeHandler {
markClean();
}
+ /**
+ * Caret offset on the last line of generated SQL. Trailing line breaks are
skipped so the caret
+ * sits on the last statement, not on a blank line under it.
+ */
+ static int generatedSqlCaretOffset(String sql) {
+ String text = Const.NVL(sql, "");
+ int end = text.length();
+ while (end > 0) {
+ char c = text.charAt(end - 1);
+ if (c != '\n' && c != '\r') {
+ break;
+ }
+ end--;
+ }
+ return end;
+ }
+
+ /**
+ * Focus the editor and put the caret on the last line. Generated SQL must
not leave the caret in
+ * the tree filter, which is the first text control in the workbench.
+ */
+ public void focusEndOfScript() {
+ if (editor == null || editor.isDisposed()) {
+ return;
+ }
+ editor.setCaretPosition(generatedSqlCaretOffset(editor.getText()));
+ editor.setFocus();
+ }
+
public String getSqlText() {
return editor.getText();
}
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbench.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbench.java
index 0133555fac..17663d4f2e 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbench.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbench.java
@@ -1065,7 +1065,7 @@ public class DatabaseWorkbench extends Composite
implements TabClosable {
host.getVariables(), node.getSchemaName(), node.getObjectName());
sql = "SELECT * FROM " + qualified;
}
- openSqlTab(freshMeta, sql, null, sql, false);
+ openGeneratedSql(freshMeta, sql);
}
@GuiToolbarElement(
@@ -1107,7 +1107,7 @@ public class DatabaseWorkbench extends Composite
implements TabClosable {
ddl = db.getCreateTableStatement(node.getObjectName(), fields,
null, false, null, true);
}
String sql = ddl;
- host.asyncExec(() -> openSqlTab(meta, sql, null, sql, true));
+ host.asyncExec(() -> openGeneratedSql(meta, sql));
});
}
@@ -1290,7 +1290,8 @@ public class DatabaseWorkbench extends Composite
implements TabClosable {
/**
* Select {@code meta} in the tree, start a background connect/refresh if
needed, and open a SQL
- * tab with {@code sql} immediately so the user can edit and run while
schemas load.
+ * tab with {@code sql} immediately so the user can edit and run while
schemas load. Generated SQL
+ * is not a user edit, so the tab stays clean.
*/
public void openSuggestedSql(DatabaseMeta meta, String sql) {
if (meta == null || isDisposed()) {
@@ -1302,12 +1303,52 @@ public class DatabaseWorkbench extends Composite
implements TabClosable {
}
DatabaseMeta effectiveMeta = state.getDatabaseMeta();
selectConnection(effectiveMeta.getName());
- openSqlTab(effectiveMeta, Const.NVL(sql, ""), null, Const.NVL(sql, ""),
true);
+ openGeneratedSql(effectiveMeta, sql);
if (!state.isConnected()) {
connect(state);
}
}
+ /**
+ * Open generated SQL (DDL, a suggested query, truncate) without marking the
tab changed, and put
+ * the caret on the last line of the script.
+ */
+ private DatabaseSqlEditorTab openGeneratedSql(DatabaseMeta meta, String sql)
{
+ String text = Const.NVL(sql, "");
+ DatabaseSqlEditorTab tab = openSqlTab(meta, text, null, text, false);
+ if (!text.isEmpty()) {
+ focusGeneratedSqlEditor(tab);
+ }
+ return tab;
+ }
+
+ /**
+ * Move focus off the tree filter after the shell's initial focus and any
activation that follows
+ * it. One async run loses to that first-child focus on GTK.
+ */
+ private void focusGeneratedSqlEditor(DatabaseSqlEditorTab tab) {
+ if (tab == null || host == null) {
+ return;
+ }
+ host.asyncExec(
+ () -> {
+ if (!generatedSqlEditorAlive(tab)) {
+ return;
+ }
+ tab.focusEndOfScript();
+ host.asyncExec(
+ () -> {
+ if (generatedSqlEditorAlive(tab)) {
+ tab.focusEndOfScript();
+ }
+ });
+ });
+ }
+
+ private boolean generatedSqlEditorAlive(DatabaseSqlEditorTab tab) {
+ return !isDisposed() && tab.getControl() != null &&
!tab.getControl().isDisposed();
+ }
+
DatabaseConnectionState ensureConnection(DatabaseMeta meta) {
return ensureConnection(meta, host, connections, items,
this::safeRebuildTree);
}
diff --git
a/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseSqlEditorTabTest.java
b/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseSqlEditorTabTest.java
index fcda5e7dd5..f82fc05f49 100644
---
a/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseSqlEditorTabTest.java
+++
b/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseSqlEditorTabTest.java
@@ -58,4 +58,16 @@ class DatabaseSqlEditorTabTest {
assertTrue(DatabaseSqlEditorTab.isModifiedFromClean("SELECT 2", "SELECT
1"));
assertTrue(DatabaseSqlEditorTab.isModifiedFromClean("SELECT 1", ""));
}
+
+ @Test
+ void generatedSqlCaretSitsOnTheLastStatement() {
+ String statement = "CREATE TABLE t (id INT);";
+ assertEquals(
+ statement.length(),
DatabaseSqlEditorTab.generatedSqlCaretOffset(statement + "\n"));
+ assertEquals(
+ statement.length(),
DatabaseSqlEditorTab.generatedSqlCaretOffset(statement + "\r\n\n"));
+ assertEquals(0, DatabaseSqlEditorTab.generatedSqlCaretOffset(null));
+ assertEquals(0, DatabaseSqlEditorTab.generatedSqlCaretOffset("\r\n"));
+ assertEquals(statement.length(),
DatabaseSqlEditorTab.generatedSqlCaretOffset(statement));
+ }
}