diff --git a/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DBGConfigurationPanel.java b/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DBGConfigurationPanel.java index a64ad74a02c615158d507a1cc6f518a29e521e3c..b1de403000f99500fd566fcd19ba346e505b6913 100644 --- a/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DBGConfigurationPanel.java +++ b/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DBGConfigurationPanel.java @@ -24,7 +24,7 @@ import java.util.Map; public interface DBGConfigurationPanel { - void createPanel(@NotNull Composite parent); + void createPanel(@NotNull Composite parent, DBGConfigurationPanelContainer container); void loadConfiguration(@NotNull DBPDataSourceContainer dataSource, @NotNull Map configuration); diff --git a/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DBGConfigurationPanelContainer.java b/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DBGConfigurationPanelContainer.java new file mode 100644 index 0000000000000000000000000000000000000000..3b8baf78262e368949aa6895ea53b163bb133d89 --- /dev/null +++ b/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DBGConfigurationPanelContainer.java @@ -0,0 +1,35 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jkiss.dbeaver.debug.ui; + +import org.jkiss.dbeaver.model.DBPDataSourceContainer; +import org.jkiss.dbeaver.model.runtime.DBRRunnableContext; + +/** + * Panel container + */ +public interface DBGConfigurationPanelContainer { + + DBPDataSourceContainer getDataSource(); + + void updateDialogState(); + + void setWarningMessage(String message); + + DBRRunnableContext getRunnableContext(); + +} diff --git a/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DatabaseDebugConfigurationTab.java b/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DatabaseDebugConfigurationTab.java index 222480b9016ff5ea751b12b1248ffed96b8c300b..c4f496767ab7b702a645d30ef58cf0ca9476ff67 100644 --- a/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DatabaseDebugConfigurationTab.java +++ b/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DatabaseDebugConfigurationTab.java @@ -39,10 +39,12 @@ import org.jkiss.dbeaver.debug.internal.ui.DebugUIMessages; import org.jkiss.dbeaver.model.DBIcon; import org.jkiss.dbeaver.model.DBPDataSourceContainer; import org.jkiss.dbeaver.model.DBPImage; +import org.jkiss.dbeaver.model.runtime.DBRRunnableContext; import org.jkiss.dbeaver.registry.DataSourceDescriptor; import org.jkiss.dbeaver.registry.DataSourceProviderRegistry; import org.jkiss.dbeaver.registry.DataSourceRegistry; import org.jkiss.dbeaver.registry.driver.DriverDescriptor; +import org.jkiss.dbeaver.runtime.RunnableContextDelegate; import org.jkiss.dbeaver.runtime.ui.DBUserInterface; import org.jkiss.dbeaver.ui.DBeaverIcons; import org.jkiss.dbeaver.ui.UIUtils; @@ -53,7 +55,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -public class DatabaseDebugConfigurationTab extends AbstractLaunchConfigurationTab { +public class DatabaseDebugConfigurationTab extends AbstractLaunchConfigurationTab implements DBGConfigurationPanelContainer { private DebugConfigurationPanelDescriptor selectedDebugType; private DBGConfigurationPanel selectedDebugPanel; @@ -161,11 +163,12 @@ public class DatabaseDebugConfigurationTab extends AbstractLaunchConfigurationTa for (Control c : panelPlaceholder.getChildren()) { c.dispose(); } + if (debugPanel != null) { try { selectedDebugType = debugPanel; selectedDebugPanel = debugPanel.createPanel(); - selectedDebugPanel.createPanel(panelPlaceholder); + selectedDebugPanel.createPanel(panelPlaceholder, this); if (dataSource != null && currentConfiguration != null) { try { selectedDebugPanel.loadConfiguration(dataSource, currentConfiguration.getAttributes()); @@ -285,4 +288,25 @@ public class DatabaseDebugConfigurationTab extends AbstractLaunchConfigurationTa return connectionCombo.getSelectedItem() != null && selectedDebugType != null; } + @Override + public DBPDataSourceContainer getDataSource() { + return connectionCombo.getSelectedItem(); + } + + @Override + public void updateDialogState() { + setDirty(true); + updateLaunchConfigurationDialog(); + } + + @Override + public void setWarningMessage(String message) { + super.setWarningMessage(message); + } + + @Override + public DBRRunnableContext getRunnableContext() { + return new RunnableContextDelegate(getLaunchConfigurationDialog()); + } + } diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/META-INF/MANIFEST.MF b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/META-INF/MANIFEST.MF index e6dae378a015b3105c86c33e5f128a8bae419a1a..ee4626aa57c4a24368e11c8b9361a03ae5f92f95 100644 --- a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/META-INF/MANIFEST.MF +++ b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/META-INF/MANIFEST.MF @@ -10,4 +10,5 @@ Require-Bundle: org.eclipse.core.runtime, org.jkiss.dbeaver.ext.postgresql, org.jkiss.dbeaver.core, org.jkiss.dbeaver.debug.core -Export-Package: org.jkiss.dbeaver.ext.postgresql.debug.core +Export-Package: org.jkiss.dbeaver.ext.postgresql.debug, + org.jkiss.dbeaver.ext.postgresql.debug.core diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/PostgreDebugConstants.java b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/PostgreDebugConstants.java index 6efc4e6444cda7589b737aad60ccb1741ccb7e93..a229de519e23c536643f2136f66877eaadb5db1f 100644 --- a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/PostgreDebugConstants.java +++ b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/PostgreDebugConstants.java @@ -17,8 +17,6 @@ */ package org.jkiss.dbeaver.ext.postgresql.debug; -import org.jkiss.dbeaver.debug.DBGConstants; - public class PostgreDebugConstants { public static final String ATTR_SCRIPT_TEXT = "PG.ATTR_SCRIPT_TEXT"; //$NON-NLS-1$ @@ -26,7 +24,9 @@ public class PostgreDebugConstants { public static final String ATTR_ATTACH_KIND = "PG.ATTR_ATTACH_KIND"; //$NON-NLS-1$ public static final String ATTR_ATTACH_PROCESS = "PG.ATTACH_PROCESS"; //$NON-NLS-1$ public static final String ATTR_PROCEDURE_NAME = "PG.ATTR_PROCEDURE_NAME"; //$NON-NLS-1$ - public static final String ATTR_PROCEDURE_OID = "PG.ATTR_PROCEDURE_OID"; //$NON-NLS-1$ + public static final String ATTR_FUNCTION_OID = "PG.ATTR_FUNCTION_OID"; //$NON-NLS-1$ + public static final String ATTR_DATABASE_NAME = "PG.ATTR_DATABASE_NAME"; //$NON-NLS-1$ + public static final String ATTR_SCHEMA_NAME = "PG.ATTR_SCHEMA_NAME"; //$NON-NLS-1$ public static final String ATTACH_KIND_LOCAL = "LOCAL"; //$NON-NLS-1$ public static final String ATTACH_KIND_GLOBAL = "GLOBAL"; //$NON-NLS-1$ diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/core/PostgreSqlDebugCore.java b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/core/PostgreSqlDebugCore.java index 312b84387bc4c1b254ac57e7f0096c1ecc8885d0..de306de53e898b09307be5e899c40dcaf1703b59 100644 --- a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/core/PostgreSqlDebugCore.java +++ b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/core/PostgreSqlDebugCore.java @@ -63,7 +63,7 @@ public class PostgreSqlDebugCore { ILaunchConfigurationWorkingCopy workingCopy = DebugCore.createConfiguration(container, CONFIGURATION_TYPE, name); workingCopy.setAttribute(DBGConstants.ATTR_DATASOURCE_ID, dataSourceContainer.getId()); - workingCopy.setAttribute(PostgreDebugConstants.ATTR_PROCEDURE_OID, String.valueOf(procedure.getObjectId())); + workingCopy.setAttribute(PostgreDebugConstants.ATTR_FUNCTION_OID, String.valueOf(procedure.getObjectId())); workingCopy.setAttribute(PostgreDebugConstants.ATTR_PROCEDURE_NAME, procedureName); workingCopy.setAttribute(PostgreDebugConstants.ATTR_SCRIPT_TEXT, DebugCore.composeScriptText(procedure)); diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/PostgreResolver.java b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/PostgreResolver.java index 86e56926e8a69f3f319e587d7763ff3ffe3d4770..dc0e568ed863df9ea68670729d6382d699367229 100644 --- a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/PostgreResolver.java +++ b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/PostgreResolver.java @@ -63,7 +63,7 @@ public class PostgreResolver implements DBGResolver { HashMap context = new HashMap(); if (databaseObject instanceof PostgreProcedure) { PostgreProcedure procedure = (PostgreProcedure) databaseObject; - context.put(PostgreDebugConstants.ATTR_PROCEDURE_OID, procedure.getObjectId()); + context.put(PostgreDebugConstants.ATTR_FUNCTION_OID, procedure.getObjectId()); } return context; } diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/impl/PostgreDebugController.java b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/impl/PostgreDebugController.java index c76e28d68a5ef2c3daa63b11d0d81141da37d62c..4926b508d3b9ddebac019bd8024c86a790ca9a16 100644 --- a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/impl/PostgreDebugController.java +++ b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/impl/PostgreDebugController.java @@ -41,7 +41,7 @@ public class PostgreDebugController extends DBGBaseController { try { PostgreDebugSession pgSession = new PostgreDebugSession(monitor,this); - int oid = CommonUtils.toInt(configuration.get(PostgreDebugConstants.ATTR_PROCEDURE_OID)); + int oid = CommonUtils.toInt(configuration.get(PostgreDebugConstants.ATTR_FUNCTION_OID)); int pid = CommonUtils.toInt(configuration.get(PostgreDebugConstants.ATTR_ATTACH_PROCESS)); String kind = String.valueOf(configuration.get(PostgreDebugConstants.ATTR_ATTACH_KIND)); boolean global = PostgreDebugConstants.ATTACH_KIND_GLOBAL.equals(kind); @@ -56,7 +56,7 @@ public class PostgreDebugController extends DBGBaseController { @Override public DBGBreakpointDescriptor describeBreakpoint(Map attributes) { - Object oid = attributes.get(PostgreDebugConstants.ATTR_PROCEDURE_OID); + Object oid = attributes.get(PostgreDebugConstants.ATTR_FUNCTION_OID); Object lineNumber = attributes.get(IMarker.LINE_NUMBER); long parsed = Long.parseLong(String.valueOf(lineNumber)); return new PostgreDebugBreakpointDescriptor(oid, parsed, false); diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.ui/src/org/jkiss/dbeaver/ext/postgresql/debug/ui/internal/PostgreDebugPanelFunction.java b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.ui/src/org/jkiss/dbeaver/ext/postgresql/debug/ui/internal/PostgreDebugPanelFunction.java index 77b8e07128223e94f5c6b02915e673a206a8a50d..e344445ea87a363a816fa39f478e6e9041b33e5f 100644 --- a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.ui/src/org/jkiss/dbeaver/ext/postgresql/debug/ui/internal/PostgreDebugPanelFunction.java +++ b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.ui/src/org/jkiss/dbeaver/ext/postgresql/debug/ui/internal/PostgreDebugPanelFunction.java @@ -18,42 +18,122 @@ package org.jkiss.dbeaver.ext.postgresql.debug.ui.internal; +import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.*; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Text; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.core.DBeaverCore; import org.jkiss.dbeaver.debug.ui.DBGConfigurationPanel; +import org.jkiss.dbeaver.debug.ui.DBGConfigurationPanelContainer; import org.jkiss.dbeaver.ext.postgresql.debug.PostgreDebugConstants; +import org.jkiss.dbeaver.ext.postgresql.model.PostgreDataSource; +import org.jkiss.dbeaver.ext.postgresql.model.PostgreDatabase; +import org.jkiss.dbeaver.ext.postgresql.model.PostgreProcedure; +import org.jkiss.dbeaver.ext.postgresql.model.PostgreSchema; +import org.jkiss.dbeaver.model.DBIcon; import org.jkiss.dbeaver.model.DBPDataSourceContainer; +import org.jkiss.dbeaver.model.navigator.DBNDatabaseNode; +import org.jkiss.dbeaver.model.navigator.DBNModel; +import org.jkiss.dbeaver.model.navigator.DBNNode; +import org.jkiss.dbeaver.model.struct.DBSInstance; +import org.jkiss.dbeaver.model.struct.DBSObjectContainer; +import org.jkiss.dbeaver.ui.DBeaverIcons; import org.jkiss.dbeaver.ui.UIUtils; +import org.jkiss.dbeaver.ui.controls.CSmartCombo; +import org.jkiss.dbeaver.ui.controls.CSmartSelector; +import org.jkiss.dbeaver.ui.dialogs.BrowseObjectDialog; +import org.jkiss.utils.CommonUtils; +import java.lang.reflect.InvocationTargetException; import java.util.Map; public class PostgreDebugPanelFunction implements DBGConfigurationPanel { + private DBGConfigurationPanelContainer container; private Button kindLocal; private Button kindGlobal; - private Combo functionText; + private CSmartCombo functionCombo; private Text processIdText; + private SelectionListener listener = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + container.updateDialogState(); + } + }; + private PostgreProcedure selectedFunction; @Override - public void createPanel(Composite parent) { + public void createPanel(Composite parent, DBGConfigurationPanelContainer container) { + this.container = container; + { Group kindGroup = UIUtils.createControlGroup(parent, "Attach type", 2, GridData.HORIZONTAL_ALIGN_BEGINNING, SWT.DEFAULT); kindLocal = new Button(kindGroup, SWT.RADIO); kindLocal.setText("Local"); + kindLocal.addSelectionListener(listener); kindGlobal = new Button(kindGroup, SWT.RADIO); kindGlobal.setText("Global"); + kindGlobal.addSelectionListener(listener); } { Group functionGroup = UIUtils.createControlGroup(parent, "Function", 2, GridData.VERTICAL_ALIGN_BEGINNING, SWT.DEFAULT); - functionText = UIUtils.createLabelCombo(functionGroup, "Function", "", SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY); + UIUtils.createControlLabel(functionGroup, "Function"); + functionCombo = new CSmartSelector(functionGroup, SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY, new LabelProvider() { + @Override + public Image getImage(Object element) { + return DBeaverIcons.getImage(DBIcon.TREE_PROCEDURE); + } + + @Override + public String getText(Object element) { + if (element == null) { + return "N/A"; + } + return ((PostgreProcedure)element).getFullQualifiedSignature(); + } + }) { + @Override + protected void dropDown(boolean drop) { + if (drop) { + DBNModel navigatorModel = DBeaverCore.getInstance().getNavigatorModel(); + DBNDatabaseNode dsNode = navigatorModel.getNodeByObject(container.getDataSource()); + if (dsNode != null) { + DBNNode curNode = selectedFunction == null ? null : navigatorModel.getNodeByObject(selectedFunction); + DBNNode node = BrowseObjectDialog.selectObject( + parent.getShell(), + "Select function to debug", + dsNode, + curNode, + new Class[]{DBSInstance.class, DBSObjectContainer.class, PostgreProcedure.class}, + new Class[]{PostgreProcedure.class}); + if (node instanceof DBNDatabaseNode && ((DBNDatabaseNode) node).getObject() instanceof PostgreProcedure) { + functionCombo.removeAll(); + selectedFunction = (PostgreProcedure) ((DBNDatabaseNode) node).getObject(); + functionCombo.addItem(selectedFunction); + functionCombo.select(selectedFunction); + container.updateDialogState(); + } + } + } + + } + }; + functionCombo.addItem(null); GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); - gd.widthHint = UIUtils.getFontHeight(functionText) * 40 + 10; - functionText.setLayoutData(gd); + gd.widthHint = UIUtils.getFontHeight(functionCombo) * 40 + 10; + functionCombo.setLayoutData(gd); processIdText = UIUtils.createLabelText(functionGroup, "Process ID", "", SWT.BORDER, new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); - gd.widthHint = UIUtils.getFontHeight(functionText) * 10 + 10; + gd.widthHint = UIUtils.getFontHeight(processIdText) * 10 + 10; processIdText.setLayoutData(gd); } } @@ -66,15 +146,68 @@ public class PostgreDebugPanelFunction implements DBGConfigurationPanel { } else { kindLocal.setSelection(true); } + Object processId = configuration.get(PostgreDebugConstants.ATTR_ATTACH_PROCESS); + processIdText.setText(processId == null ? "" : processId.toString()); + + long functionId = CommonUtils.toLong(configuration.get(PostgreDebugConstants.ATTR_FUNCTION_OID)); + String databaseName = (String)configuration.get(PostgreDebugConstants.ATTR_DATABASE_NAME); + String schemaName = (String)configuration.get(PostgreDebugConstants.ATTR_SCHEMA_NAME); + if (functionId != 0 && dataSource != null) { + try { + container.getRunnableContext().run(true, true, monitor -> { + try { + if (!dataSource.isConnected()) { + dataSource.connect(monitor, true, true); + } + PostgreDataSource ds = (PostgreDataSource) dataSource.getDataSource(); + PostgreDatabase database = ds.getDatabase(databaseName); + if (database != null) { + PostgreSchema schema = database.getSchema(monitor, schemaName); + if (schema != null) { + selectedFunction = schema.getProcedure(monitor, functionId); + } else { + container.setWarningMessage("Schema '" + schemaName + "' not found"); + } + } else { + container.setWarningMessage("Database '" + databaseName + "' not found"); + } + } catch (DBException e) { + throw new InvocationTargetException(e); + } + }); + } catch (InvocationTargetException e) { + container.setWarningMessage(e.getTargetException().getMessage()); + } catch (InterruptedException e) { + // ignore + } + } + if (selectedFunction != null) { + functionCombo.addItem(selectedFunction); + functionCombo.select(selectedFunction); + } else { + container.setWarningMessage("Function '" + functionId + "' not found in schema '" + schemaName + "'"); + } } @Override public void saveConfiguration(DBPDataSourceContainer dataSource, Map configuration) { + configuration.put(PostgreDebugConstants.ATTR_ATTACH_KIND, + kindGlobal.getSelection() ? PostgreDebugConstants.ATTACH_KIND_GLOBAL : PostgreDebugConstants.ATTACH_KIND_LOCAL); + configuration.put(PostgreDebugConstants.ATTR_ATTACH_PROCESS, processIdText.getText()); + if (selectedFunction != null) { + configuration.put(PostgreDebugConstants.ATTR_FUNCTION_OID, selectedFunction.getObjectId()); + configuration.put(PostgreDebugConstants.ATTR_DATABASE_NAME, selectedFunction.getDatabase().getName()); + configuration.put(PostgreDebugConstants.ATTR_SCHEMA_NAME, selectedFunction.getSchema().getName()); + } else { + configuration.remove(PostgreDebugConstants.ATTR_FUNCTION_OID); + configuration.remove(PostgreDebugConstants.ATTR_DATABASE_NAME); + configuration.remove(PostgreDebugConstants.ATTR_SCHEMA_NAME); + } } @Override public boolean isValid() { - return false; + return selectedFunction != null; } }