This is an automated email from the ASF dual-hosted git repository.
mattcasters 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 87a70d25b2 Issue #8361 : Link RDBMS metadata editor with the Database
perspective (#8405)
87a70d25b2 is described below
commit 87a70d25b2c6c61645abea718617ef48cdb3034b
Author: Matt Casters <[email protected]>
AuthorDate: Wed Sep 16 09:34:09 2026 +0200
Issue #8361 : Link RDBMS metadata editor with the Database perspective
(#8405)
Add Open in Database on the connection editor and Edit connection on the
Database workbench. Explorer SQL/DDL/Truncate use the floating workbench.
SqlEditor remains as a public API for other callers.
fixes #8361
---
.../ROOT/pages/hop-gui/perspective-database.adoc | 5 +-
.../pages/metadata-types/rdbms-connection.adoc | 1 +
.../hop/ui/core/database/DatabaseMetaEditor.java | 75 +++++++++++++++-------
.../database/dialog/DatabaseExplorerDialog.java | 42 ++++++------
.../main/java/org/apache/hop/ui/hopgui/HopGui.java | 5 ++
.../perspective/database/DatabasePerspective.java | 13 ++++
.../perspective/database/DatabaseWorkbench.java | 54 +++++++++++++++-
.../database/DatabaseWorkbenchViews.java | 34 ++++++++++
.../dialog/messages/messages_en_US.properties | 1 +
.../database/messages/messages_en_US.properties | 4 ++
.../database/messages/messages_en_US.properties | 2 +
.../perspective/DisabledPerspectivesTest.java | 1 +
.../database/DatabaseWorkbenchReloadMetaTest.java | 24 +++++--
.../database/DatabaseWorkbenchViewsTest.java | 31 +++++++++
14 files changed, 242 insertions(+), 50 deletions(-)
diff --git
a/docs/hop-user-manual/modules/ROOT/pages/hop-gui/perspective-database.adoc
b/docs/hop-user-manual/modules/ROOT/pages/hop-gui/perspective-database.adoc
index 07f745c61c..00ecbcc45f 100644
--- a/docs/hop-user-manual/modules/ROOT/pages/hop-gui/perspective-database.adoc
+++ b/docs/hop-user-manual/modules/ROOT/pages/hop-gui/perspective-database.adoc
@@ -40,6 +40,7 @@ Toolbar:
* *Connect* — load schemas and their tables (background; does not freeze Hop
Gui)
* *Disconnect* — drop the loaded schema list
* *Refresh* — reload the selected connected connection, or the connection list
+* *Edit connection* — open this connection in the Metadata perspective (or a
dialog if that perspective is disabled)
* *Open SQL editor* — new SQL tab for the selected connection (`SELECT * FROM
table` when a table is selected)
* *Generate DDL* — `CREATE TABLE` for the selected table, opened in a SQL tab
* *Preview table* — run `SELECT` with a dialect-aware row limit (the **Query
row limit** in Configuration → Plugins → Database Perspective, default 1000)
@@ -88,7 +89,9 @@
image::hop-gui/database/database-perspective-popup-dialog.png[The floating Datab
Each placement has its own workbench instance (connection tree, SQL tabs,
operations). The perspective stays available with `Ctrl+Shift+D`. SQL editor
tabs (connection, file or buffer, unsaved edits) are remembered per project
when you close the window or dock and when you restart Hop Gui. Query results
are not stored.
-**SQL** on a table-output (or bulk-loader, lookup, update, …) transform dialog
opens this floating window on the transform's connection: the schema/table tree
refreshes in the background while you edit and run the generated SQL. The same
happens from the database explorer (Open SQL, Generate DDL, Truncate).
+**SQL** on a table-output (or bulk-loader, lookup, update, …) transform dialog
opens this floating window on the transform's connection: the schema/table tree
refreshes in the background while you edit and run the generated SQL. The same
happens from the database explorer (Open SQL, Generate DDL, Truncate). The
explorer toolbar also has *Open in Database perspective*, which closes the
explorer and switches to this perspective on the explorer's connection.
+
+On the relational database connection metadata editor, *Open in Database* does
the same from the other direction: it activates this perspective on that
connection so you can explore and query immediately.
== See also
diff --git
a/docs/hop-user-manual/modules/ROOT/pages/metadata-types/rdbms-connection.adoc
b/docs/hop-user-manual/modules/ROOT/pages/metadata-types/rdbms-connection.adoc
index dac163b2e2..78e306971d 100644
---
a/docs/hop-user-manual/modules/ROOT/pages/metadata-types/rdbms-connection.adoc
+++
b/docs/hop-user-manual/modules/ROOT/pages/metadata-types/rdbms-connection.adoc
@@ -34,6 +34,7 @@ Transforms and actions store the *name* of a relational
database connection. Whe
image::hop-gui/validate-database-connections-on-save-warning-dialog.png[Database
connections save warning,width="90%"]
+The connection editor has *Explore* (the classic table picker) and *Open in
Database* (the xref:hop-gui/perspective-database.adoc[Database perspective], to
browse schemas and run SQL). From that perspective, *Edit connection* opens
this metadata editor.
== Related Plugins
diff --git
a/ui/src/main/java/org/apache/hop/ui/core/database/DatabaseMetaEditor.java
b/ui/src/main/java/org/apache/hop/ui/core/database/DatabaseMetaEditor.java
index 94865c37cb..2bdcda2614 100644
--- a/ui/src/main/java/org/apache/hop/ui/core/database/DatabaseMetaEditor.java
+++ b/ui/src/main/java/org/apache/hop/ui/core/database/DatabaseMetaEditor.java
@@ -64,6 +64,7 @@ import org.apache.hop.ui.core.widget.NamingSchemeTypes;
import org.apache.hop.ui.core.widget.TableView;
import org.apache.hop.ui.core.widget.TextVar;
import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.perspective.database.DatabaseWorkbenchViews;
import org.apache.hop.ui.hopgui.perspective.metadata.MetadataPerspective;
import org.apache.hop.ui.util.HelpUtils;
import org.eclipse.swt.SWT;
@@ -1106,29 +1107,53 @@ public class DatabaseMetaEditor extends
MetadataEditor<DatabaseMeta> {
}
private void explore() {
+ if (!canExploreDatabase()) {
+ return;
+ }
+ DatabaseMeta meta = new DatabaseMeta();
+ getWidgetsContent(meta);
+ try {
+ DatabaseExplorerDialog dialog =
+ new DatabaseExplorerDialog(
+ getShell(),
+ SWT.NONE,
+ manager.getVariables(),
+ meta,
+ manager.getSerializer().loadAll(),
+ true,
+ true);
+ dialog.open();
+ } catch (Exception e) {
+ new ErrorDialog(getShell(), "Error", "Error exploring database", e);
+ }
+ }
+
+ private void openInDatabase() {
+ if (!canExploreDatabase()) {
+ return;
+ }
+ DatabaseMeta meta = new DatabaseMeta();
+ getWidgetsContent(meta);
+ if (StringUtils.isBlank(meta.getName())) {
+ MessageBox box = new MessageBox(getShell(), SWT.OK | SWT.ICON_ERROR);
+ box.setText(BaseMessages.getString(PKG,
"DatabaseDialog.OpenInDatabase.NameRequired.Title"));
+ box.setMessage(
+ BaseMessages.getString(PKG,
"DatabaseDialog.OpenInDatabase.NameRequired.Message"));
+ box.open();
+ return;
+ }
+ DatabaseWorkbenchViews.openInDatabase(hopGui, meta, "");
+ }
+
+ private boolean canExploreDatabase() {
if (!getMetadata().isExploringDisabled()) {
- DatabaseMeta meta = new DatabaseMeta();
- getWidgetsContent(meta);
- try {
- DatabaseExplorerDialog dialog =
- new DatabaseExplorerDialog(
- getShell(),
- SWT.NONE,
- manager.getVariables(),
- meta,
- manager.getSerializer().loadAll(),
- true,
- true);
- dialog.open();
- } catch (Exception e) {
- new ErrorDialog(getShell(), "Error", "Error exploring database", e);
- }
- } else {
- MessageBox mb = new MessageBox(HopGui.getInstance().getShell(), SWT.OK |
SWT.ICON_ERROR);
- mb.setText(BaseMessages.getString(PKG,
"DatabaseDialog.Exploring.Disabled.title"));
- mb.setMessage(BaseMessages.getString(PKG,
"DatabaseDialog.Exploring.Disabled.description"));
- mb.open();
+ return true;
}
+ MessageBox mb = new MessageBox(getShell(), SWT.OK | SWT.ICON_ERROR);
+ mb.setText(BaseMessages.getString(PKG,
"DatabaseDialog.Exploring.Disabled.title"));
+ mb.setMessage(BaseMessages.getString(PKG,
"DatabaseDialog.Exploring.Disabled.description"));
+ mb.open();
+ return false;
}
private void onHelpDatabaseType() {
@@ -1506,11 +1531,17 @@ public class DatabaseMetaEditor extends
MetadataEditor<DatabaseMeta> {
wExplore.setText(BaseMessages.getString(PKG,
"DatabaseDialog.button.Explore"));
wExplore.addListener(SWT.Selection, e -> explore());
+ Button wOpenInDatabase = new Button(parent, SWT.PUSH);
+ wOpenInDatabase.setText(BaseMessages.getString(PKG,
"DatabaseDialog.button.OpenInDatabase"));
+ wOpenInDatabase.setToolTipText(
+ BaseMessages.getString(PKG,
"DatabaseDialog.button.OpenInDatabase.Tooltip"));
+ wOpenInDatabase.addListener(SWT.Selection, e -> openInDatabase());
+
Button wTest = new Button(parent, SWT.PUSH);
wTest.setText(BaseMessages.getString(PKG, "System.Button.Test"));
wTest.addListener(SWT.Selection, e -> test());
- return new Button[] {wGenerateVariables, wExplore, wTest};
+ return new Button[] {wGenerateVariables, wExplore, wOpenInDatabase, wTest};
}
/**
diff --git
a/ui/src/main/java/org/apache/hop/ui/core/database/dialog/DatabaseExplorerDialog.java
b/ui/src/main/java/org/apache/hop/ui/core/database/dialog/DatabaseExplorerDialog.java
index 76ad966459..5973e93363 100644
---
a/ui/src/main/java/org/apache/hop/ui/core/database/dialog/DatabaseExplorerDialog.java
+++
b/ui/src/main/java/org/apache/hop/ui/core/database/dialog/DatabaseExplorerDialog.java
@@ -24,7 +24,6 @@ import java.util.List;
import lombok.Getter;
import lombok.Setter;
import org.apache.hop.core.Const;
-import org.apache.hop.core.DbCache;
import org.apache.hop.core.Props;
import org.apache.hop.core.database.Catalog;
import org.apache.hop.core.database.Database;
@@ -38,9 +37,7 @@ import
org.apache.hop.core.gui.plugin.key.GuiOsxKeyboardShortcut;
import org.apache.hop.core.gui.plugin.menu.GuiMenuElement;
import org.apache.hop.core.gui.plugin.toolbar.GuiToolbarElement;
import org.apache.hop.core.gui.plugin.toolbar.GuiToolbarElementType;
-import org.apache.hop.core.logging.ILogChannel;
import org.apache.hop.core.logging.ILoggingObject;
-import org.apache.hop.core.logging.LogChannel;
import org.apache.hop.core.logging.LoggingObject;
import org.apache.hop.core.row.IRowMeta;
import org.apache.hop.core.search.SearchMatcher;
@@ -66,6 +63,8 @@ import org.apache.hop.ui.core.widget.HopTree;
import org.apache.hop.ui.hopgui.HopGui;
import org.apache.hop.ui.hopgui.HopGuiKeyHandler;
import org.apache.hop.ui.hopgui.ToolbarFacade;
+import org.apache.hop.ui.hopgui.perspective.database.DatabaseWorkbenchDialog;
+import org.apache.hop.ui.hopgui.perspective.database.DatabaseWorkbenchViews;
import org.apache.hop.ui.pipeline.transform.BaseTransformDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
@@ -107,6 +106,8 @@ public class DatabaseExplorerDialog extends Dialog {
"DatabaseExplorerDialog-Toolbar-10060-ShowLayout";
public static final String TOOLBAR_ITEM_SQL_SELECT =
"DatabaseExplorerDialog-Toolbar-10070-SqlSelect";
+ public static final String TOOLBAR_ITEM_OPEN_PERSPECTIVE =
+ "DatabaseExplorerDialog-Toolbar-20000-OpenPerspective";
public static final String CONTEXT_MENU_PREVIEW_100 =
"DatabaseExplorerDialog-ContextMenu-10010-Preview100";
@@ -141,10 +142,8 @@ public class DatabaseExplorerDialog extends Dialog {
/** Debounced search action so we don't rebuild the tree on every keystroke.
*/
private final Runnable filterRunnable = this::updateTree;
- private final ILogChannel log;
private final DatabaseMeta databaseMeta;
private final IVariables variables;
- private final DbCache dbCache;
private final ILoggingObject loggingObject;
private final List<DatabaseMeta> databases;
private final boolean justLook;
@@ -191,19 +190,11 @@ public class DatabaseExplorerDialog extends Dialog {
filterUseRegEx = false;
selectedSchemaName = null;
selectedTableName = null;
- log = new LogChannel("DBExplorer");
- dbCache = DbCache.getInstance();
}
public boolean open() {
- if (Const.isLinux()) {
- shell =
- new Shell(
- getParent(),
- SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX |
SWT.MIN);
- } else {
- shell = new Shell(getParent(), SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX |
SWT.MIN);
- }
+ // Modeless so the floating Database window (SQL / DDL) can stay usable on
Linux.
+ shell = new Shell(getParent(), SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX |
SWT.MIN);
PropsUi.setLook(shell);
shell.setImage(GuiResource.getInstance().getImageDatabase());
// Do not include the connection name in the title (to save/restore the
dialog box dimensions
@@ -866,7 +857,7 @@ public class DatabaseExplorerDialog extends Dialog {
new Database(loggingObject, variables, targetDatabaseMeta)) {
String sql =
targetDatabase.getCreateTableStatement(table, rowMeta, null,
false, null, true);
- openSqlEditor(sql);
+ openSqlEditor(targetDatabaseMeta, sql);
}
}
} catch (HopDatabaseException dbe) {
@@ -923,9 +914,24 @@ public class DatabaseExplorerDialog extends Dialog {
}
}
+ @GuiToolbarElement(
+ root = GUI_PLUGIN_TOOLBAR_PARENT_ID,
+ id = TOOLBAR_ITEM_OPEN_PERSPECTIVE,
+ type = GuiToolbarElementType.BUTTON,
+ toolTip = "i18n::DatabaseExplorerDialog.Toolbar.OpenPerspective.Tooltip",
+ image = "ui/images/database-perspective.svg",
+ separator = true)
+ public void openInDatabasePerspective() {
+ cancel();
+ DatabaseWorkbenchViews.openInDatabase(databaseMeta, "");
+ }
+
protected void openSqlEditor(String sql) {
- SqlEditor dialog = new SqlEditor(shell, SWT.NONE, variables, databaseMeta,
dbCache, sql);
- dialog.open();
+ openSqlEditor(databaseMeta, sql);
+ }
+
+ protected void openSqlEditor(DatabaseMeta meta, String sql) {
+ DatabaseWorkbenchDialog.openSql(meta, sql);
}
public void dispose() {
diff --git a/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java
index faff4df3c5..0abc13c653 100644
--- a/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java
@@ -138,6 +138,7 @@ import
org.apache.hop.ui.hopgui.perspective.HopPerspectivePlugin;
import org.apache.hop.ui.hopgui.perspective.HopPerspectivePluginType;
import org.apache.hop.ui.hopgui.perspective.IHopPerspective;
import
org.apache.hop.ui.hopgui.perspective.configuration.ConfigurationPerspective;
+import org.apache.hop.ui.hopgui.perspective.database.DatabasePerspective;
import org.apache.hop.ui.hopgui.perspective.database.DatabaseSqlEditorTab;
import org.apache.hop.ui.hopgui.perspective.execution.ExecutionPerspective;
import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerPerspective;
@@ -3011,6 +3012,10 @@ public class HopGui
return
HopGui.getInstance().getPerspectiveManager().findPerspective(MetadataPerspective.class);
}
+ public static DatabasePerspective getDatabasePerspective() {
+ return
HopGui.getInstance().getPerspectiveManager().findPerspective(DatabasePerspective.class);
+ }
+
public static ExecutionPerspective getExecutionPerspective() {
return
HopGui.getInstance().getPerspectiveManager().findPerspective(ExecutionPerspective.class);
}
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabasePerspective.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabasePerspective.java
index 35f57e39f3..22087e618b 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabasePerspective.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabasePerspective.java
@@ -18,6 +18,7 @@
package org.apache.hop.ui.hopgui.perspective.database;
import java.util.List;
+import org.apache.hop.core.Const;
import org.apache.hop.core.database.DatabaseMeta;
import org.apache.hop.core.gui.plugin.GuiPlugin;
import org.apache.hop.core.gui.plugin.key.GuiKeyboardShortcut;
@@ -202,6 +203,18 @@ public class DatabasePerspective implements
IHopPerspective, TabClosable, IDatab
workbench.openSqlFile(filename, connection, buffer, dirty);
}
+ /**
+ * Bring this perspective to the front, select {@code meta} in the tree,
connect in the
+ * background, and open a SQL tab with {@code sql} (may be empty).
+ */
+ public void openConnection(DatabaseMeta meta, String sql) {
+ if (!isInitialized() || meta == null) {
+ return;
+ }
+ activate();
+ workbench.openSuggestedSql(meta, Const.NVL(sql, ""));
+ }
+
public List<String> connectionNames() {
if (!isInitialized()) {
return List.of();
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 aa3c101b89..a0395af582 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
@@ -53,6 +53,7 @@ import org.apache.hop.ui.core.gui.GuiMenuWidgets;
import org.apache.hop.ui.core.gui.GuiResource;
import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
import org.apache.hop.ui.core.gui.IToolbarContainer;
+import org.apache.hop.ui.core.metadata.MetadataManager;
import org.apache.hop.ui.core.widget.TreeMemory;
import org.apache.hop.ui.hopgui.BackgroundThreadFacade;
import org.apache.hop.ui.hopgui.HopGui;
@@ -64,6 +65,7 @@ import org.apache.hop.ui.hopgui.perspective.TabCloseHandler;
import org.apache.hop.ui.hopgui.perspective.TabItemHandler;
import
org.apache.hop.ui.hopgui.perspective.database.config.DatabasePerspectiveConfig;
import
org.apache.hop.ui.hopgui.perspective.database.config.DatabasePerspectiveConfigSingleton;
+import org.apache.hop.ui.hopgui.perspective.metadata.MetadataPerspective;
import org.apache.hop.ui.hopgui.shared.SashFormMemory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
@@ -96,6 +98,8 @@ public class DatabaseWorkbench extends Composite implements
TabClosable {
public static final String TOOLBAR_ITEM_CONNECT =
"DatabaseWorkbench-Toolbar-10000-Connect";
public static final String TOOLBAR_ITEM_DISCONNECT =
"DatabaseWorkbench-Toolbar-10010-Disconnect";
public static final String TOOLBAR_ITEM_REFRESH =
"DatabaseWorkbench-Toolbar-10020-Refresh";
+ public static final String TOOLBAR_ITEM_EDIT_METADATA =
+ "DatabaseWorkbench-Toolbar-10025-EditMetadata";
public static final String TOOLBAR_ITEM_SQL =
"DatabaseWorkbench-Toolbar-10030-SqlEditor";
public static final String TOOLBAR_ITEM_DDL =
"DatabaseWorkbench-Toolbar-10040-GenerateDdl";
public static final String TOOLBAR_ITEM_PREVIEW =
"DatabaseWorkbench-Toolbar-10050-Preview";
@@ -106,6 +110,8 @@ public class DatabaseWorkbench extends Composite implements
TabClosable {
public static final String CONTEXT_MENU_CONNECT =
"DatabaseWorkbench-ContextMenu-10000-Connect";
public static final String CONTEXT_MENU_DISCONNECT =
"DatabaseWorkbench-ContextMenu-10010-Disconnect";
+ public static final String CONTEXT_MENU_EDIT_METADATA =
+ "DatabaseWorkbench-ContextMenu-10020-EditMetadata";
public static final String CONTEXT_MENU_SQL =
"DatabaseWorkbench-ContextMenu-10030-SqlEditor";
public static final String CONTEXT_MENU_DDL =
"DatabaseWorkbench-ContextMenu-10040-GenerateDdl";
public static final String CONTEXT_MENU_PREVIEW =
"DatabaseWorkbench-ContextMenu-10050-Preview";
@@ -776,6 +782,7 @@ public class DatabaseWorkbench extends Composite implements
TabClosable {
toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_CONNECT, hasConnection &&
!connected);
toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_DISCONNECT, hasConnection &&
connected);
toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_REFRESH, true);
+ toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_EDIT_METADATA,
hasConnection);
toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_SQL, hasConnection);
toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_DDL, table);
toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_PREVIEW, table);
@@ -785,6 +792,7 @@ public class DatabaseWorkbench extends Composite implements
TabClosable {
enableMenu(CONTEXT_MENU_CONNECT, hasConnection && !connected);
enableMenu(CONTEXT_MENU_DISCONNECT, hasConnection && connected);
+ enableMenu(CONTEXT_MENU_EDIT_METADATA, hasConnection);
enableMenu(CONTEXT_MENU_SQL, hasConnection);
enableMenu(CONTEXT_MENU_DDL, table);
enableMenu(CONTEXT_MENU_PREVIEW, table);
@@ -981,6 +989,45 @@ public class DatabaseWorkbench extends Composite
implements TabClosable {
reloadConnections();
}
+ @GuiToolbarElement(
+ root = GUI_PLUGIN_TOOLBAR_PARENT_ID,
+ id = TOOLBAR_ITEM_EDIT_METADATA,
+ toolTip = "i18n::DatabasePerspective.Toolbar.EditMetadata.Tooltip",
+ image = "ui/images/metadata.svg")
+ @GuiMenuElement(
+ root = GUI_PLUGIN_CONTEXT_MENU_PARENT_ID,
+ parentId = GUI_PLUGIN_CONTEXT_MENU_PARENT_ID,
+ id = CONTEXT_MENU_EDIT_METADATA,
+ label = "i18n::DatabasePerspective.Menu.EditMetadata",
+ image = "ui/images/metadata.svg")
+ public void editSelectedConnection() {
+ DatabaseConnectionState state = selectedState();
+ if (state == null || state.getDatabaseMeta() == null) {
+ return;
+ }
+ String name = state.getDatabaseMeta().getName();
+ if (Utils.isEmpty(name)) {
+ return;
+ }
+ HopGui hopGui = host.getHopGui();
+ if (hopGui == null) {
+ return;
+ }
+ MetadataManager<DatabaseMeta> manager =
+ new MetadataManager<>(
+ host.getVariables(), host.getMetadataProvider(),
DatabaseMeta.class, host.getShell());
+ MetadataPerspective perspective =
+ hopGui.getPerspectiveManager() == null
+ ? null
+ :
hopGui.getPerspectiveManager().findPerspective(MetadataPerspective.class);
+ if (perspective != null) {
+ perspective.activate();
+ manager.editWithEditor(name);
+ } else {
+ manager.editMetadataInDialog(name);
+ }
+ }
+
@GuiToolbarElement(
root = GUI_PLUGIN_TOOLBAR_PARENT_ID,
id = TOOLBAR_ITEM_SQL,
@@ -1265,11 +1312,12 @@ public class DatabaseWorkbench extends Composite
implements TabClosable {
if (meta == null || connections == null) {
return null;
}
- DatabaseMeta freshMeta =
- reloadConnectionMeta(meta.getName(), host, connections, items,
onTreeChanged);
- if (freshMeta == null && host != null && host.getMetadataProvider() !=
null) {
+ if (Utils.isEmpty(meta.getName())) {
return null;
}
+ DatabaseMeta freshMeta =
+ reloadConnectionMeta(meta.getName(), host, connections, items,
onTreeChanged);
+ // Not in the serializer: still use the caller-supplied definition
(unsaved editor, explorer).
DatabaseMeta effectiveMeta = freshMeta != null ? freshMeta : meta;
DatabaseConnectionState state = connections.get(effectiveMeta.getName());
if (state == null) {
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchViews.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchViews.java
index 7c19ae0e14..0222ceb2fe 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchViews.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchViews.java
@@ -17,6 +17,7 @@
package org.apache.hop.ui.hopgui.perspective.database;
+import org.apache.hop.core.database.DatabaseMeta;
import org.apache.hop.core.gui.plugin.GuiPlugin;
import org.apache.hop.core.gui.plugin.menu.GuiMenuElement;
import org.apache.hop.i18n.BaseMessages;
@@ -66,6 +67,39 @@ public class DatabaseWorkbenchViews {
DatabaseWorkbenchDialog.open(hopGui);
}
+ /**
+ * Open {@code meta} in the Database perspective when that perspective is
enabled, otherwise in
+ * the floating Database window. {@code sql} may be empty.
+ */
+ public static void openInDatabase(DatabaseMeta meta, String sql) {
+ HopGui hopGui;
+ try {
+ hopGui = HopGui.peekInstance();
+ } catch (Throwable e) {
+ hopGui = null;
+ }
+ openInDatabase(hopGui, meta, sql);
+ }
+
+ /**
+ * Open {@code meta} in the Database perspective when that perspective is
enabled, otherwise in
+ * the floating Database window. {@code sql} may be empty.
+ */
+ public static void openInDatabase(HopGui hopGui, DatabaseMeta meta, String
sql) {
+ if (meta == null) {
+ return;
+ }
+ if (hopGui != null && hopGui.getPerspectiveManager() != null) {
+ DatabasePerspective perspective =
+
hopGui.getPerspectiveManager().findPerspective(DatabasePerspective.class);
+ if (perspective != null) {
+ perspective.openConnection(meta, sql);
+ return;
+ }
+ }
+ DatabaseWorkbenchDialog.openSql(meta, sql);
+ }
+
/** True when the floating Database window is already open. */
public static boolean isDialogOpen(HopGui hopGui) {
if (hopGui == null || hopGui.getShell() == null ||
hopGui.getShell().isDisposed()) {
diff --git
a/ui/src/main/resources/org/apache/hop/ui/core/database/dialog/messages/messages_en_US.properties
b/ui/src/main/resources/org/apache/hop/ui/core/database/dialog/messages/messages_en_US.properties
index 72bbf3d143..6a88d76058 100644
---
a/ui/src/main/resources/org/apache/hop/ui/core/database/dialog/messages/messages_en_US.properties
+++
b/ui/src/main/resources/org/apache/hop/ui/core/database/dialog/messages/messages_en_US.properties
@@ -27,6 +27,7 @@ DatabaseExplorerDialog.Menu.ShowLayout=Show layout...
DatabaseExplorerDialog.Menu.ShowSize=Number of rows...
DatabaseExplorerDialog.Menu.Truncate=Truncate table...
DatabaseExplorerDialog.Toolbar.SQLSelect.Tooltip=Generate SQL Select...
+DatabaseExplorerDialog.Toolbar.OpenPerspective.Tooltip=Open this connection in
the Database perspective
DatabaseExplorerDialog.Toolbar.Preview.Tooltip=Preview first 100 rows...
DatabaseExplorerDialog.Toolbar.ShowLayout.Tooltip=Show layout...
DatabaseExplorerDialog.NoConnectionsKnown.Message=At this point no other
connections are available to generate the DDL for.
diff --git
a/ui/src/main/resources/org/apache/hop/ui/core/database/messages/messages_en_US.properties
b/ui/src/main/resources/org/apache/hop/ui/core/database/messages/messages_en_US.properties
index 41d216a9f5..6ae91017b7 100644
---
a/ui/src/main/resources/org/apache/hop/ui/core/database/messages/messages_en_US.properties
+++
b/ui/src/main/resources/org/apache/hop/ui/core/database/messages/messages_en_US.properties
@@ -18,6 +18,10 @@
DatabaseDialog.AdvancedTab.title=Advanced
DatabaseDialog.button.DownloadDriver=Download driver
DatabaseDialog.button.Explore=Explore
+DatabaseDialog.button.OpenInDatabase=Open in Database
+DatabaseDialog.button.OpenInDatabase.Tooltip=Open this connection in the
Database perspective to explore and query
+DatabaseDialog.OpenInDatabase.NameRequired.Title=Connection name required
+DatabaseDialog.OpenInDatabase.NameRequired.Message=Please enter a connection
name before opening the Database perspective.
DatabaseDialog.button.GenerateVariables=Generate variables
DatabaseDialog.GenerateVariables.NameRequired.Title=Connection name required
DatabaseDialog.GenerateVariables.NameRequired.Message=Please enter a
connection name before generating variables. The name is used as a prefix (for
example EDW_HOSTNAME).
diff --git
a/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/database/messages/messages_en_US.properties
b/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/database/messages/messages_en_US.properties
index cb8c4fbfab..21ccda47e7 100644
---
a/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/database/messages/messages_en_US.properties
+++
b/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/database/messages/messages_en_US.properties
@@ -28,6 +28,7 @@ DatabasePerspective.Tree.Synonyms=Synonyms
DatabasePerspective.Toolbar.Connect.Tooltip=Connect and list schemas and tables
DatabasePerspective.Toolbar.Disconnect.Tooltip=Forget loaded schemas and
tables for this connection
DatabasePerspective.Toolbar.Refresh.Tooltip=Reload the selected connection, or
the connection list
+DatabasePerspective.Toolbar.EditMetadata.Tooltip=Edit this connection in the
Metadata perspective
DatabasePerspective.Toolbar.SqlEditor.Tooltip=Open a new SQL editor for the
selected connection
DatabasePerspective.Toolbar.GenerateDdl.Tooltip=Generate CREATE TABLE for the
selected table
DatabasePerspective.Toolbar.Preview.Tooltip=Preview the selected table using
the query row limit from the Database perspective options
@@ -36,6 +37,7 @@ DatabasePerspective.Toolbar.Float.Tooltip=Open a floating
Database window
DatabasePerspective.Toolbar.Dock.Tooltip=Open Database in the bottom dock
DatabasePerspective.Menu.Connect=Connect
DatabasePerspective.Menu.Disconnect=Disconnect
+DatabasePerspective.Menu.EditMetadata=Edit connection
DatabasePerspective.Menu.SqlEditor=Open SQL editor
DatabasePerspective.Menu.GenerateDdl=Generate DDL
DatabasePerspective.Menu.Preview=Preview table
diff --git
a/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/DisabledPerspectivesTest.java
b/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/DisabledPerspectivesTest.java
index ea3dbbf6fd..33ba539efb 100644
---
a/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/DisabledPerspectivesTest.java
+++
b/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/DisabledPerspectivesTest.java
@@ -88,6 +88,7 @@ class DisabledPerspectivesTest {
perspective.activate();
perspective.clearSearchFilters();
perspective.openSqlFile("x.sql", null, "select 1", false);
+ perspective.openConnection(null, "select 1");
});
assertTrue(perspective.getItems().isEmpty());
assertTrue(perspective.connectionNames().isEmpty());
diff --git
a/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchReloadMetaTest.java
b/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchReloadMetaTest.java
index 71bc2eb7c5..5bca83a252 100644
---
a/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchReloadMetaTest.java
+++
b/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchReloadMetaTest.java
@@ -118,19 +118,31 @@ class DatabaseWorkbenchReloadMetaTest {
}
@Test
- void ensureConnectionReturnsNullWhenDeleted() throws Exception {
+ void ensureConnectionFallsBackToSuppliedMetaWhenNotInSerializer() throws
Exception {
Map<String, DatabaseConnectionState> connections = new LinkedHashMap<>();
DatabaseMeta meta = mock(DatabaseMeta.class);
- when(meta.getName()).thenReturn("deleted-conn");
- connections.put("deleted-conn", new DatabaseConnectionState(meta));
+ when(meta.getName()).thenReturn("unsaved-conn");
- when(serializer.exists("deleted-conn")).thenReturn(false);
+ when(serializer.exists("unsaved-conn")).thenReturn(false);
DatabaseConnectionState state =
DatabaseWorkbench.ensureConnection(meta, host, connections, List.of(),
null);
- assertNull(state);
- assertFalse(connections.containsKey("deleted-conn"));
+ assertNotNull(state);
+ assertSame(meta, state.getDatabaseMeta());
+ assertTrue(connections.containsKey("unsaved-conn"));
+ }
+
+ @Test
+ void ensureConnectionReturnsNullForBlankName() {
+ Map<String, DatabaseConnectionState> connections = new LinkedHashMap<>();
+ DatabaseMeta emptyName = mock(DatabaseMeta.class);
+ when(emptyName.getName()).thenReturn("");
+ assertNull(DatabaseWorkbench.ensureConnection(emptyName, host,
connections, List.of(), null));
+
+ DatabaseMeta unnamed = mock(DatabaseMeta.class);
+ when(unnamed.getName()).thenReturn(null);
+ assertNull(DatabaseWorkbench.ensureConnection(unnamed, host, connections,
List.of(), null));
}
@Test
diff --git
a/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchViewsTest.java
b/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchViewsTest.java
index 9b857ba218..98e1c28d4e 100644
---
a/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchViewsTest.java
+++
b/ui/src/test/java/org/apache/hop/ui/hopgui/perspective/database/DatabaseWorkbenchViewsTest.java
@@ -18,8 +18,13 @@
package org.apache.hop.ui.hopgui.perspective.database;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import java.lang.reflect.Method;
+import org.apache.hop.core.gui.plugin.toolbar.GuiToolbarElement;
+import org.apache.hop.ui.core.database.dialog.DatabaseExplorerDialog;
import org.junit.jupiter.api.Test;
class DatabaseWorkbenchViewsTest {
@@ -49,4 +54,30 @@ class DatabaseWorkbenchViewsTest {
void openSqlIsInertWithoutHopGui() {
assertDoesNotThrow(() -> DatabaseWorkbenchDialog.openSql(null, "SELECT
1"));
}
+
+ @Test
+ void openInDatabaseIsInertWithoutHopGui() {
+ assertDoesNotThrow(() -> DatabaseWorkbenchViews.openInDatabase(null, null,
"SELECT 1"));
+ assertDoesNotThrow(() -> DatabaseWorkbenchViews.openInDatabase(null,
"SELECT 1"));
+ }
+
+ @Test
+ void editMetadataToolbarIsRegisteredOnTheWorkbench() throws Exception {
+ Method method =
DatabaseWorkbench.class.getMethod("editSelectedConnection");
+ GuiToolbarElement element = method.getAnnotation(GuiToolbarElement.class);
+ assertNotNull(element);
+ assertEquals(DatabaseWorkbench.GUI_PLUGIN_TOOLBAR_PARENT_ID,
element.root());
+ assertEquals(DatabaseWorkbench.TOOLBAR_ITEM_EDIT_METADATA, element.id());
+ assertEquals("ui/images/metadata.svg", element.image());
+ }
+
+ @Test
+ void openPerspectiveToolbarIsRegisteredOnTheExplorer() throws Exception {
+ Method method =
DatabaseExplorerDialog.class.getMethod("openInDatabasePerspective");
+ GuiToolbarElement element = method.getAnnotation(GuiToolbarElement.class);
+ assertNotNull(element);
+ assertEquals(DatabaseExplorerDialog.GUI_PLUGIN_TOOLBAR_PARENT_ID,
element.root());
+ assertEquals(DatabaseExplorerDialog.TOOLBAR_ITEM_OPEN_PERSPECTIVE,
element.id());
+ assertEquals("ui/images/database-perspective.svg", element.image());
+ }
}