From a1ea5818070fcfccdd657e780cba977122bdeee7 Mon Sep 17 00:00:00 2001 From: serge-rider Date: Fri, 4 May 2018 17:11:52 +0300 Subject: [PATCH] Debug panel UI - function parameters --- .../sql/ProcedureParameterBindDialog.java | 166 ++++++++++++++++++ .../ui/DatabaseDebugConfigurationTab.java | 15 +- .../debug/PostgreDebugConstants.java | 1 + .../internal/PostgreDebugPanelFunction.java | 50 ++++-- .../struct/rdb/DBSProcedureParameterKind.java | 5 + 5 files changed, 218 insertions(+), 19 deletions(-) create mode 100644 plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/runtime/sql/ProcedureParameterBindDialog.java diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/runtime/sql/ProcedureParameterBindDialog.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/runtime/sql/ProcedureParameterBindDialog.java new file mode 100644 index 0000000000..4b4cac3feb --- /dev/null +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/runtime/sql/ProcedureParameterBindDialog.java @@ -0,0 +1,166 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2017 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.runtime.sql; + +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.dialogs.StatusDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.*; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.core.DBeaverUI; +import org.jkiss.dbeaver.model.DBIcon; +import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor; +import org.jkiss.dbeaver.model.struct.rdb.DBSProcedure; +import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureParameter; +import org.jkiss.dbeaver.runtime.ui.DBUserInterface; +import org.jkiss.dbeaver.ui.DBeaverIcons; +import org.jkiss.dbeaver.ui.UIUtils; +import org.jkiss.dbeaver.ui.controls.CustomTableEditor; +import org.jkiss.dbeaver.utils.GeneralUtils; +import org.jkiss.utils.CommonUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Parameter binding + */ +public class ProcedureParameterBindDialog extends StatusDialog { + + private static final String DIALOG_ID = "DBeaver.ProcedureParameterBindDialog";//$NON-NLS-1$ + + private DBSProcedure procedure; + private List parameters; + private Map values = new HashMap<>(); + + public ProcedureParameterBindDialog(Shell shell, DBSProcedure procedure, Map values) + { + super(shell); + this.procedure = procedure; + this.parameters = new ArrayList<>(); + + try { + this.parameters.addAll(procedure.getParameters(new VoidProgressMonitor())); + } catch (DBException e) { + DBUserInterface.getInstance().showError("Can't get parameters", "Error getting procedure papameters", e); + } + + this.values = new HashMap<>(values); + } + + @Override + protected IDialogSettings getDialogBoundsSettings() + { + return UIUtils.getDialogSettings(DIALOG_ID); + } + + @Override + protected boolean isResizable() + { + return true; + } + + + @Override + protected Control createDialogArea(Composite parent) + { + getShell().setText(procedure.getProcedureType().name() + " " + procedure.getName() + " parameter(s)"); + final Composite composite = (Composite)super.createDialogArea(parent); + + final Table paramTable = new Table(composite, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); + final GridData gd = new GridData(GridData.FILL_BOTH); + gd.widthHint = 400; + gd.heightHint = 200; + paramTable.setLayoutData(gd); + paramTable.setHeaderVisible(true); + paramTable.setLinesVisible(true); + + final TableColumn nameColumn = UIUtils.createTableColumn(paramTable, SWT.LEFT, "Name"); + nameColumn.setWidth(100); + final TableColumn valueColumn = UIUtils.createTableColumn(paramTable, SWT.LEFT, "Value"); + valueColumn.setWidth(200); + final TableColumn typeColumn = UIUtils.createTableColumn(paramTable, SWT.LEFT, "Type"); + typeColumn.setWidth(60); + final TableColumn kindColumn = UIUtils.createTableColumn(paramTable, SWT.LEFT, "Kind"); + kindColumn.setWidth(40); + + for (DBSProcedureParameter param : parameters) { + TableItem item = new TableItem(paramTable, SWT.NONE); + item.setData(param); + item.setImage(DBeaverIcons.getImage(DBIcon.TREE_ATTRIBUTE)); + item.setText(0, param.getName()); + Object value = values.get(param); + item.setText(1, CommonUtils.toString(value, "")); + item.setText(2, param.getParameterType().getFullTypeName()); + item.setText(3, param.getParameterKind().getTitle()); + } + + final CustomTableEditor tableEditor = new CustomTableEditor(paramTable) { + { + firstTraverseIndex = 1; + lastTraverseIndex = 1; + editOnEnter = false; + } + @Override + protected Control createEditor(Table table, int index, TableItem item) { + if (index != 1) { + return null; + } + DBSProcedureParameter param = (DBSProcedureParameter) item.getData(); + Text editor = new Text(table, SWT.BORDER); + editor.setText(CommonUtils.toString(values.get(param), "")); + editor.selectAll(); + return editor; + } + @Override + protected void saveEditorValue(Control control, int index, TableItem item) { + DBSProcedureParameter param = (DBSProcedureParameter) item.getData(); + String newValue = ((Text) control).getText(); + item.setText(1, newValue); + + values.put(param, newValue); + } + }; + + if (!parameters.isEmpty()) { + DBeaverUI.asyncExec(() -> { + paramTable.select(0); + tableEditor.showEditor(paramTable.getItem(0), 1); + }); + } + + updateStatus(GeneralUtils.makeInfoStatus("Use Tab to switch.")); + return composite; + } + + @Override + protected void okPressed() + { + super.okPressed(); + } + + public List getParameters() { + return parameters; + } + + public Map getValues() { + return values; + } +} 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 c4f496767a..0ba3369ca2 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 @@ -260,14 +260,17 @@ public class DatabaseDebugConfigurationTab extends AbstractLaunchConfigurationTa Map attrs = new HashMap<>(); selectedDebugPanel.saveConfiguration(dataSource, attrs); for (Map.Entry entry : attrs.entrySet()) { - if (entry.getValue() == null) { + Object value = entry.getValue(); + if (value == null) { configuration.removeAttribute(entry.getKey()); - } else if (entry.getValue() instanceof Integer) { - configuration.setAttribute(entry.getKey(), (Integer)entry.getValue()); - } else if (entry.getValue() instanceof Boolean) { - configuration.setAttribute(entry.getKey(), (Boolean)entry.getValue()); + } else if (value instanceof Integer) { + configuration.setAttribute(entry.getKey(), (Integer) value); + } else if (value instanceof Boolean) { + configuration.setAttribute(entry.getKey(), (Boolean) value); + } else if (value instanceof List) { + configuration.setAttribute(entry.getKey(), (List)value); } else { - configuration.setAttribute(entry.getKey(), entry.getValue().toString()); + configuration.setAttribute(entry.getKey(), value.toString()); } } } 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 a229de519e..d67e73d724 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 @@ -27,6 +27,7 @@ public class PostgreDebugConstants { 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 ATTR_FUNCTION_PARAMETERS = "PG.ATTR_FUNCTION_PARAMETERS"; //$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.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 486f5b81c6..0b6f863177 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,6 +18,7 @@ package org.jkiss.dbeaver.ext.postgresql.debug.ui.internal; +import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; @@ -40,11 +41,10 @@ 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.runtime.VoidProgressMonitor; -import org.jkiss.dbeaver.model.sql.SQLQueryParameter; import org.jkiss.dbeaver.model.struct.DBSInstance; import org.jkiss.dbeaver.model.struct.DBSObjectContainer; -import org.jkiss.dbeaver.runtime.sql.SQLQueryParameterBindDialog; +import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureParameter; +import org.jkiss.dbeaver.runtime.sql.ProcedureParameterBindDialog; import org.jkiss.dbeaver.ui.DBeaverIcons; import org.jkiss.dbeaver.ui.UIUtils; import org.jkiss.dbeaver.ui.controls.CSmartCombo; @@ -54,6 +54,7 @@ import org.jkiss.utils.CommonUtils; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -64,9 +65,11 @@ public class PostgreDebugPanelFunction implements DBGConfigurationPanel { private Button kindGlobal; private CSmartCombo functionCombo; private Text processIdText; - private PostgreProcedure selectedFunction; private Button configParametersButton; + private PostgreProcedure selectedFunction; + private Map parameterValues = new HashMap<>(); + @Override public void createPanel(Composite parent, DBGConfigurationPanelContainer container) { this.container = container; @@ -78,6 +81,7 @@ public class PostgreDebugPanelFunction implements DBGConfigurationPanel { @Override public void widgetSelected(SelectionEvent e) { processIdText.setEnabled(kindGlobal.getSelection()); + configParametersButton.setEnabled(kindLocal.getSelection()); container.updateDialogState(); } }; @@ -144,15 +148,11 @@ public class PostgreDebugPanelFunction implements DBGConfigurationPanel { if (selectedFunction == null) { return; } - List parameters = new ArrayList<>(); - List funcParams = selectedFunction.getParameters(null); - for (int i = 0; i < funcParams.size(); i++) { - PostgreProcedureParameter param = funcParams.get(i); - parameters.add(new SQLQueryParameter(i, param.getName())); + ProcedureParameterBindDialog dialog = new ProcedureParameterBindDialog(parent.getShell(), selectedFunction, parameterValues); + if (dialog.open() == IDialogConstants.OK_ID) { + parameterValues.clear(); + parameterValues.putAll(dialog.getValues()); } - SQLQueryParameterBindDialog dialog = new SQLQueryParameterBindDialog(parent.getShell(), parameters); - dialog.open(); - super.widgetSelected(e); } }); gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); @@ -174,6 +174,7 @@ public class PostgreDebugPanelFunction implements DBGConfigurationPanel { } else { kindLocal.setSelection(true); } + configParametersButton.setEnabled(kindLocal.getSelection()); processIdText.setEnabled(kindGlobal.getSelection()); Object processId = configuration.get(PostgreDebugConstants.ATTR_ATTACH_PROCESS); @@ -211,12 +212,28 @@ public class PostgreDebugPanelFunction implements DBGConfigurationPanel { // ignore } } + + if (selectedFunction != null) { + @SuppressWarnings("unchecked") + List paramValues = (List) configuration.get(PostgreDebugConstants.ATTR_FUNCTION_PARAMETERS); + if (paramValues != null) { + List parameters = selectedFunction.getParameters(null); + if (parameters.size() == paramValues.size()) { + for (int i = 0; i < parameters.size(); i++) { + PostgreProcedureParameter param = parameters.get(i); + parameterValues.put(param, paramValues.get(i)); + } + } + } + } configParametersButton.setEnabled(selectedFunction != null); if (selectedFunction != null) { functionCombo.addItem(selectedFunction); functionCombo.select(selectedFunction); } else { - container.setWarningMessage("Function '" + functionId + "' not found in schema '" + schemaName + "'"); + if (functionId != 0) { + container.setWarningMessage("Function '" + functionId + "' not found in schema '" + schemaName + "'"); + } } } @@ -230,10 +247,17 @@ public class PostgreDebugPanelFunction implements DBGConfigurationPanel { 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()); + List paramValues = new ArrayList<>(); + for (PostgreProcedureParameter param : selectedFunction.getParameters(null)) { + Object value = parameterValues.get(param); + paramValues.add(value == null ? null : value.toString()); + } + configuration.put(PostgreDebugConstants.ATTR_FUNCTION_PARAMETERS, paramValues); } else { configuration.remove(PostgreDebugConstants.ATTR_FUNCTION_OID); configuration.remove(PostgreDebugConstants.ATTR_DATABASE_NAME); configuration.remove(PostgreDebugConstants.ATTR_SCHEMA_NAME); + configuration.remove(PostgreDebugConstants.ATTR_FUNCTION_PARAMETERS); } } diff --git a/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/model/struct/rdb/DBSProcedureParameterKind.java b/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/model/struct/rdb/DBSProcedureParameterKind.java index c9b660bca3..cab1f36df1 100644 --- a/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/model/struct/rdb/DBSProcedureParameterKind.java +++ b/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/model/struct/rdb/DBSProcedureParameterKind.java @@ -29,4 +29,9 @@ public enum DBSProcedureParameterKind RETURN, RESULTSET, TABLE, + ; + + public String getTitle() { + return name(); + } } -- GitLab