提交 ba7ed43e 编写于 作者: S Serge Rider 提交者: GitHub

Merge pull request #2615 from serge-rider/2374-execute-stored-procedure

#2374 Execute stored procedure

Former-commit-id: 06d091ef
......@@ -536,4 +536,7 @@ public class CommonUtils {
return Boolean.TRUE.equals(optionValue);
}
public static String fixedLengthString(String string, int length) {
return String.format("%1$"+length+ "s", string);
}
}
......@@ -118,6 +118,9 @@ command.org.jkiss.dbeaver.core.txn.pending.name=Pending transactions
command.org.jkiss.dbeaver.core.txn.pending.description=List of all pending transactions
command.org.jkiss.dbeaver.core.transaction_mode.name=Transaction mode
command.org.jkiss.dbeaver.core.procedure.execute.name=Execute Stored Procedure
command.org.jkiss.dbeaver.core.procedure.execute.description=Open new SQL console with execute stored procedure query
command.org.jkiss.dbeaver.core.sql.editor.open.name=SQL Editor
command.org.jkiss.dbeaver.core.sql.editor.open.description=Open SQL editor (existing or new)
command.org.jkiss.dbeaver.core.sql.editor.recent.name=Recent SQL Editor
......
......@@ -103,7 +103,7 @@
class="org.jkiss.dbeaver.ui.editors.sql.generator.SQLUtilsPropertyTester"
id="org.jkiss.dbeaver.ui.editors.sql.generator.SQLUtilsPropertyTester"
namespace="org.jkiss.dbeaver.ui.editors.sql.util"
properties="canGenerate,hasTools"
properties="canGenerate,hasTools,isProcedure"
type="org.eclipse.ui.IWorkbenchPart"/>
<propertyTester
class="org.jkiss.dbeaver.ui.controls.resultset.ResultSetPropertyTester"
......@@ -243,6 +243,7 @@
<command id="org.jkiss.dbeaver.core.sql.editor.recent" name="%command.org.jkiss.dbeaver.core.sql.editor.recent.name" description="%command.org.jkiss.dbeaver.core.sql.editor.recent.description" categoryId="org.jkiss.dbeaver.core.database"/>
<command id="org.jkiss.dbeaver.core.sql.editor.create" name="%command.org.jkiss.dbeaver.core.sql.editor.create.name" description="%command.org.jkiss.dbeaver.core.sql.editor.create.description" categoryId="org.jkiss.dbeaver.core.database"/>
<command id="org.jkiss.dbeaver.core.sql.editor.forSelection" name="%command.org.jkiss.dbeaver.core.sql.editor.forSelection.name" description="%command.org.jkiss.dbeaver.core.sql.editor.forSelection.description" categoryId="org.jkiss.dbeaver.core.database"/>
<command id="command.org.jkiss.dbeaver.core.procedure.execute" name="%command.org.jkiss.dbeaver.core.procedure.execute.name" description="%command.org.jkiss.dbeaver.core.procedure.execute.description" categoryId="org.jkiss.dbeaver.core.database"/>
<command id="org.jkiss.dbeaver.core.object.open" name="%command.org.jkiss.dbeaver.core.object.open.name" description="%command.org.jkiss.dbeaver.core.object.open.description" categoryId="org.jkiss.dbeaver.core.database"/>
<command id="org.jkiss.dbeaver.core.object.create" name="%command.org.jkiss.dbeaver.core.object.create.name" description="%command.org.jkiss.dbeaver.core.object.create.description" categoryId="org.jkiss.dbeaver.core.database"/>
<command id="org.jkiss.dbeaver.core.object.delete" name="%command.org.jkiss.dbeaver.core.object.delete.name" description="%command.org.jkiss.dbeaver.core.object.delete.description" categoryId="org.jkiss.dbeaver.core.database"/>
......@@ -1005,6 +1006,12 @@
</with>
</enabledWhen>
</handler>
<handler commandId="command.org.jkiss.dbeaver.core.procedure.execute" class="org.jkiss.dbeaver.ui.editors.sql.handlers.RunProcedureConsoleHandler">
<parameter
name="org.jkiss.dbeaver.core.resource.link.file.contenttype"
value="org.jkiss.dbeaver.sql">
</parameter>
</handler>
<handler commandId="org.jkiss.dbeaver.ui.editors.sql.rename" class="org.jkiss.dbeaver.ui.editors.sql.handlers.RenameHandler">
<enabledWhen>
......@@ -2081,6 +2088,15 @@
<menuContribution allPopups="false" locationURI="popup:org.eclipse.ui.popup.any?after=tools">
<separator name="data" visible="true"/>
<command
commandId="command.org.jkiss.dbeaver.core.procedure.execute"
label="%command.org.jkiss.dbeaver.core.procedure.execute.name">
<visibleWhen>
<with variable="activePart">
<test property="org.jkiss.dbeaver.ui.editors.sql.util.isProcedure"/>
</with>
</visibleWhen>
</command>
<command
commandId="org.jkiss.dbeaver.core.sql.editor.forSelection"
label="%command.org.jkiss.dbeaver.core.sql.editor.forSelection.name">
......
......@@ -46,8 +46,12 @@ import org.jkiss.dbeaver.model.navigator.DBNNode;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.DBRRunnableWithResult;
import org.jkiss.dbeaver.model.sql.SQLConstants;
import org.jkiss.dbeaver.model.sql.SQLDataSource;
import org.jkiss.dbeaver.model.sql.SQLDialect;
import org.jkiss.dbeaver.model.sql.SQLUtils;
import org.jkiss.dbeaver.model.struct.*;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedure;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureParameter;
import org.jkiss.dbeaver.model.struct.rdb.DBSTable;
import org.jkiss.dbeaver.ui.DBeaverIcons;
import org.jkiss.dbeaver.ui.UIIcon;
......@@ -482,6 +486,24 @@ public class GenerateSQLContributor extends CompoundContributionItem {
}
}
private abstract static class ProcedureAnalysisRunner extends BaseAnalysisRunner<DBSProcedure> {
protected ProcedureAnalysisRunner(List<DBSProcedure> entities)
{
super(entities);
}
protected Collection<? extends DBSEntityAttribute> getAllAttributes(DBRProgressMonitor monitor, DBSProcedure object) throws DBException
{
return Collections.emptyList();
}
protected Collection<? extends DBSEntityAttribute> getKeyAttributes(DBRProgressMonitor monitor, DBSProcedure object) throws DBException
{
return Collections.emptyList();
}
}
private abstract static class ResultSetAnalysisRunner extends BaseAnalysisRunner<ResultSetModel> {
ResultSetAnalysisRunner(DBPDataSource dataSource, ResultSetModel model)
......@@ -795,4 +817,20 @@ public class GenerateSQLContributor extends CompoundContributionItem {
};
}
@NotNull
public static SQLGenerator<DBSProcedure> CALL_GENERATOR(final List<DBSProcedure> entities) {
return new ProcedureAnalysisRunner(entities) {
@Override
protected void generateSQL(DBRProgressMonitor monitor, StringBuilder sql, DBSProcedure proc) throws DBException {
Collection<? extends DBSProcedureParameter> parameters = proc.getParameters(monitor);
DBPDataSource dataSource = proc.getDataSource();
if (dataSource instanceof SQLDataSource) {
SQLDataSource sqlDataSource = (SQLDataSource) dataSource;
SQLDialect sqlDialect = sqlDataSource.getSQLDialect();
sqlDialect.generateStoredProcedureCall(sql, proc, parameters);
}
}
};
}
}
......@@ -19,7 +19,9 @@ package org.jkiss.dbeaver.ui.editors.sql.generator;
import org.eclipse.core.expressions.PropertyTester;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IWorkbenchPart;
import org.jkiss.dbeaver.model.sql.SQLDataSource;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedure;
import org.jkiss.dbeaver.registry.tools.ToolsRegistry;
import org.jkiss.dbeaver.ui.ActionUtils;
import org.jkiss.dbeaver.ui.controls.resultset.IResultSetSelection;
......@@ -34,6 +36,7 @@ public class SQLUtilsPropertyTester extends PropertyTester
public static final String NAMESPACE = "org.jkiss.dbeaver.ui.editors.sql.util";
public static final String PROP_CAN_GENERATE = "canGenerate";
public static final String PROP_HAS_TOOLS = "hasTools";
public static final String PROP_IS_PROCEDURE = "isProcedure";
public SQLUtilsPropertyTester() {
super();
......@@ -60,6 +63,13 @@ public class SQLUtilsPropertyTester extends PropertyTester
DBSObject object = NavigatorUtils.getSelectedObject(structuredSelection);
return object != null && !CommonUtils.isEmpty(ToolsRegistry.getInstance().getTools(structuredSelection));
}
case PROP_IS_PROCEDURE: {
DBSObject object = NavigatorUtils.getSelectedObject(structuredSelection);
return object != null &&
object instanceof DBSProcedure &&
object.getDataSource() != null &&
object.getDataSource() instanceof SQLDataSource;
}
}
return false;
}
......
......@@ -62,9 +62,16 @@ public class OpenObjectConsoleHandler extends AbstractHandler {
}
}
DBRRunnableWithResult<String> generator = GenerateSQLContributor.SELECT_GENERATOR(entities, true);
openConsole(workbenchWindow, generator, ds, "Query", true);
return null;
}
protected void openConsole(IWorkbenchWindow workbenchWindow, DBRRunnableWithResult<String> generator,
DBPDataSourceContainer ds, String title, boolean doRun) {
DBeaverUI.runInUI(workbenchWindow, generator);
String sql = generator.getResult();
SQLEditor editor = OpenHandler.openSQLConsole(workbenchWindow, ds, "Query", sql);
SQLEditor editor = OpenHandler.openSQLConsole(workbenchWindow, ds, title, sql);
if (editor != null) {
AbstractJob execJob = new AbstractJob("Execute SQL in console") {
......@@ -87,14 +94,14 @@ public class OpenObjectConsoleHandler extends AbstractHandler {
DBeaverUI.syncExec(new Runnable() {
@Override
public void run() {
editor.processSQL(false, false);
if (doRun) {
editor.processSQL(false, false);
}
}
});
}
});
execJob.schedule();
}
return null;
}
}
/*
* 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.ui.editors.sql.handlers;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.handlers.HandlerUtil;
import org.jkiss.dbeaver.core.DBeaverUI;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.runtime.AbstractJob;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.DBRRunnableWithResult;
import org.jkiss.dbeaver.model.struct.DBSEntity;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedure;
import org.jkiss.dbeaver.ui.editors.sql.SQLEditor;
import org.jkiss.dbeaver.ui.editors.sql.generator.GenerateSQLContributor;
import org.jkiss.dbeaver.ui.navigator.NavigatorUtils;
import org.jkiss.dbeaver.utils.RuntimeUtils;
import org.jkiss.utils.CommonUtils;
import java.util.ArrayList;
import java.util.List;
public class RunProcedureConsoleHandler extends OpenObjectConsoleHandler {
public RunProcedureConsoleHandler()
{
}
@Override
public Object execute(ExecutionEvent event) throws ExecutionException
{
IWorkbenchWindow workbenchWindow = HandlerUtil.getActiveWorkbenchWindow(event);
DBPDataSourceContainer ds = null;
String procName = null;
List<DBSObject> selectedObjects = NavigatorUtils.getSelectedObjects(HandlerUtil.getCurrentSelection(event));
List<DBSProcedure> entities = new ArrayList<>();
for (DBSObject object : selectedObjects) {
if (object instanceof DBSProcedure) {
DBSProcedure proc = (DBSProcedure) object;
procName = proc.getName();
entities.add(proc);
ds = object.getDataSource().getContainer();
}
}
DBRRunnableWithResult<String> generator = GenerateSQLContributor.CALL_GENERATOR(entities);
String title = "Stored procedures call";
if (entities.size() == 1 && !CommonUtils.isEmpty(procName)) {
title = procName + " call";
}
openConsole(workbenchWindow, generator, ds, title, false);
return null;
}
}
......@@ -21,8 +21,13 @@ import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.ext.generic.model.GenericSQLDialect;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCDatabaseMetaData;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCDataSource;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedure;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureParameter;
import org.jkiss.dbeaver.runtime.sql.SQLRuleProvider;
import org.jkiss.utils.CommonUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class SQLServerDialect extends GenericSQLDialect implements SQLRuleProvider {
......@@ -59,4 +64,30 @@ public class SQLServerDialect extends GenericSQLDialect implements SQLRuleProvid
@Override
public void extendRules(@NotNull List<IRule> rules, @NotNull RulePosition position) {
}
@Override
public void generateStoredProcedureCall(StringBuilder sql, DBSProcedure proc, Collection<? extends DBSProcedureParameter> parameters) {
List<DBSProcedureParameter> inParameters = new ArrayList<>();
int maxParamLength = getMaxParameterLength(parameters, inParameters);
String schemaName = proc.getParentObject().getName();
schemaName = proc.getContainer().getParentObject().getName();
sql.append("USE [" + schemaName + "]\n");
sql.append("GO\n\n");
sql.append("DECLARE @return_value int\n\n");
sql.append("EXEC\t@return_value = [" + proc.getContainer().getName() +"].[" + proc.getName() + "]\n");
for (int i = 0; i < inParameters.size(); i++) {
String name = inParameters.get(i).getName();
sql.append("\t\t" + name + " = ?");
if (i < (inParameters.size() - 1)) {
sql.append(", ");
} else {
sql.append(" ");
}
int width = maxParamLength + 70 - name.length()/2;
String typeName = inParameters.get(i).getParameterType().getFullTypeName();
sql.append(CommonUtils.fixedLengthString("-- put the " + name + " parameter value instead of '?' (" + typeName + ")\n", width));
}
sql.append("\nSELECT\t'Return Value' = @return_value\n\n");
sql.append("GO\n\n");
}
}
......@@ -25,6 +25,7 @@ import org.jkiss.dbeaver.model.impl.jdbc.JDBCDataSource;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCSQLDialect;
import org.jkiss.dbeaver.model.impl.sql.BasicSQLDialect;
import org.jkiss.dbeaver.model.sql.SQLConstants;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedure;
import org.jkiss.utils.ArrayUtils;
import java.util.Arrays;
......@@ -362,4 +363,10 @@ class OracleSQLDialect extends JDBCSQLDialect {
protected String[] getNonTransactionKeywords() {
return ORACLE_NON_TRANSACTIONAL_KEYWORDS;
}
@Override
protected String getStoredProcedureCallInitialClause(DBSProcedure proc) {
String schemaName = proc.getParentObject().getName();
return "CALL " + schemaName + "." + proc.getName() + "(\n";
}
}
......@@ -28,6 +28,9 @@ import org.jkiss.dbeaver.model.struct.DBSAttributeBase;
import org.jkiss.dbeaver.model.struct.DBSDataType;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.model.struct.DBSTypedObject;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedure;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureParameter;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureParameterKind;
import org.jkiss.utils.ArrayUtils;
import org.jkiss.utils.CommonUtils;
import org.jkiss.utils.Pair;
......@@ -521,4 +524,42 @@ public class BasicSQLDialect implements SQLDialect {
return null;
}
/**
* @param inParameters empty list to collect IN parameters
*/
protected int getMaxParameterLength(Collection<? extends DBSProcedureParameter> parameters, List<DBSProcedureParameter> inParameters) {
int maxParamLength = 0;
for (DBSProcedureParameter param : parameters) {
if (param.getParameterKind() == DBSProcedureParameterKind.IN) {
inParameters.add(param);
if (param.getName().length() > maxParamLength) {
maxParamLength = param.getName().length();
}
}
}
return maxParamLength;
}
// first line of the call stored procedure SQL (to be overridden)
protected String getStoredProcedureCallInitialClause(DBSProcedure proc) {
return "select " + proc.getName() + "(\n";
}
@Override
public void generateStoredProcedureCall(StringBuilder sql, DBSProcedure proc, Collection<? extends DBSProcedureParameter> parameters) {
List<DBSProcedureParameter> inParameters = new ArrayList<>();
getMaxParameterLength(parameters, inParameters);
sql.append(getStoredProcedureCallInitialClause(proc));
for (int i = 0; i < inParameters.size(); i++) {
sql.append("\t\t\t?");
if (i < (inParameters.size() - 1)) {
sql.append(",");
} else {
sql.append(" ");
}
String typeName = inParameters.get(i).getParameterType().getFullTypeName();
sql.append("\t-- put the " + inParameters.get(i).getName() + " parameter value instead of '?' (" + typeName + ")\n");
}
sql.append(");\n\n");
}
}
......@@ -26,8 +26,11 @@ import org.jkiss.dbeaver.model.data.DBDBinaryFormatter;
import org.jkiss.dbeaver.model.data.DBDDataFilter;
import org.jkiss.dbeaver.model.struct.DBSAttributeBase;
import org.jkiss.dbeaver.model.struct.DBSTypedObject;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedure;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureParameter;
import org.jkiss.utils.Pair;
import java.util.Collection;
import java.util.List;
import java.util.Set;
......@@ -296,4 +299,5 @@ public interface SQLDialect {
@Nullable
String getColumnTypeModifiers(@NotNull DBSTypedObject column, @NotNull String typeName, @NotNull DBPDataKind dataKind);
void generateStoredProcedureCall(StringBuilder sql, DBSProcedure proc, Collection<? extends DBSProcedureParameter> parameters);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册