未验证 提交 97682a5a 编写于 作者: S Serge Rider 提交者: GitHub

Merge pull request #13100 from dbeaver/11533_query_variables

11533 query variables
......@@ -32,6 +32,7 @@ Require-Bundle: org.eclipse.equinox.security,
org.eclipse.core.expressions,
org.eclipse.core.commands,
org.eclipse.core.resources,
com.google.gson,
org.eclipse.text;visibility:=reexport,
org.jkiss.dbeaver.model;visibility:=reexport
Bundle-Localization: OSGI-INF/l10n/bundle
......
......@@ -21,30 +21,34 @@ import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.DBPContextProvider;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
import org.jkiss.dbeaver.model.exec.DBCScriptContext;
import org.jkiss.dbeaver.model.exec.DBCScriptContextListener;
import org.jkiss.dbeaver.model.sql.registry.SQLCommandHandlerDescriptor;
import org.jkiss.dbeaver.model.sql.registry.SQLCommandsRegistry;
import org.jkiss.dbeaver.model.sql.registry.SQLVariablesRegistry;
import org.jkiss.utils.ArrayUtils;
import org.jkiss.utils.CommonUtils;
import java.io.File;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* SQL script execution context
*/
public class SQLScriptContext implements DBCScriptContext {
private final Map<String, Object> variables = new HashMap<>();
private final Map<String, VariableInfo> variables = new LinkedHashMap<>();
private final Map<String, Object> defaultParameters = new HashMap<>();
private final Map<String, Object> pragmas = new HashMap<>();
private Map<String, Object> statementPragmas;
private DBCScriptContextListener[] listeners = null;
private final Map<String, Object> data = new HashMap<>();
@Nullable
......@@ -93,16 +97,20 @@ public class SQLScriptContext implements DBCScriptContext {
@Override
public Object getVariable(String name) {
Object value = variables.get(name);
if (value == null && parentContext != null) {
value = parentContext.getVariable(name);
VariableInfo variableInfo = variables.get(name);
if (variableInfo == null && parentContext != null) {
return parentContext.getVariable(name);
}
return value;
return variableInfo == null ? null : variableInfo.value;
}
@Override
public void setVariable(String name, Object value) {
variables.put(name, value);
VariableInfo v = new VariableInfo(name, value, VariableType.VARIABLE);
VariableInfo ov = variables.put(name, v);
notifyListeners(ov == null ? DBCScriptContextListener.ContextAction.ADD : DBCScriptContextListener.ContextAction.UPDATE, v);
if (parentContext != null) {
parentContext.setVariable(name, value);
}
......@@ -110,15 +118,35 @@ public class SQLScriptContext implements DBCScriptContext {
@Override
public void removeVariable(String name) {
variables.remove(name);
VariableInfo v = variables.remove(name);
if (v != null) {
notifyListeners(DBCScriptContextListener.ContextAction.DELETE, v);
}
if (parentContext != null) {
parentContext.removeVariable(name);
}
}
@Override
public List<VariableInfo> getVariables() {
return new ArrayList<>(variables.values());
}
public void setVariables(Map<String, Object> variables) {
this.variables.clear();
this.variables.putAll(variables);
for (Map.Entry<String, Object> ve : variables.entrySet()) {
VariableInfo v = new VariableInfo(ve.getKey(), ve.getValue(), VariableType.VARIABLE);
VariableInfo ov = this.variables.put(
ve.getKey(),
v);
notifyListeners(ov == null ? DBCScriptContextListener.ContextAction.ADD : DBCScriptContextListener.ContextAction.UPDATE, v);
}
if (parentContext != null) {
parentContext.setVariables(variables);
}
}
public Object getParameterDefaultValue(String name) {
......@@ -126,7 +154,13 @@ public class SQLScriptContext implements DBCScriptContext {
}
public void setParameterDefaultValue(String name, Object value) {
defaultParameters.put(name, value);
Object op = defaultParameters.put(name, value);
notifyListeners(op == null ? DBCScriptContextListener.ContextAction.ADD : DBCScriptContextListener.ContextAction.UPDATE, name, value);
if (parentContext != null) {
parentContext.setParameterDefaultValue(name, value);
}
}
@NotNull
......@@ -220,6 +254,8 @@ public class SQLScriptContext implements DBCScriptContext {
Object varValue = variables.get(parameter.getVarName());
if (varValue == null) {
varValue = defaultParameters.get(parameter.getVarName());
} else {
varValue = ((VariableInfo)varValue).value;
}
if (varValue != null) {
parameter.setValue(CommonUtils.toString(varValue));
......@@ -233,10 +269,90 @@ public class SQLScriptContext implements DBCScriptContext {
}
public Map<String, Object> getAllParameters() {
Map<String, Object> params = new LinkedHashMap<>();
Map<String, Object> params = new LinkedHashMap<>(defaultParameters.size() + variables.size());
params.putAll(defaultParameters);
params.putAll(variables);
for (Map.Entry<String, VariableInfo> v : variables.entrySet()) {
params.put(v.getKey(), v.getValue().value);
}
return params;
}
////////////////////////////////////////////////////
// Persistence
public void loadVariables(DBPDriver driver, DBPDataSourceContainer dataSource) {
synchronized (variables) {
variables.clear();
List<VariableInfo> varList;
if (dataSource != null) {
varList = SQLVariablesRegistry.getInstance().getDataSourceVariables(dataSource);
} else if (driver != null) {
varList = SQLVariablesRegistry.getInstance().getDriverVariables(driver);
} else {
varList = new ArrayList<>();
}
for (VariableInfo v : varList) {
variables.put(v.name, v);
}
}
}
public void saveVariables(DBPDriver driver, DBPDataSourceContainer dataSource) {
ArrayList<VariableInfo> vCopy;
synchronized (variables) {
vCopy = new ArrayList<>(this.variables.values());
}
SQLVariablesRegistry.getInstance().updateVariables(driver, dataSource, vCopy);
}
public void clearVariables() {
synchronized (variables) {
variables.clear();
}
}
////////////////////////////////////////////////////
// Listeners
@Override
public synchronized void addListener(DBCScriptContextListener listener) {
if (listeners == null) {
listeners = new DBCScriptContextListener[] { listener };
} else {
listeners = ArrayUtils.add(DBCScriptContextListener.class, listeners, listener);
}
}
@Override
public synchronized void removeListener(DBCScriptContextListener listener) {
if (listeners != null) {
listeners = ArrayUtils.remove(DBCScriptContextListener.class, listeners, listener);
}
}
@Nullable
private DBCScriptContextListener[] getListenersCopy() {
synchronized (this) {
if (listeners != null) {
return Arrays.copyOf(listeners, listeners.length);
}
}
return null;
}
private void notifyListeners(DBCScriptContextListener.ContextAction contextAction, VariableInfo variableInfo) {
DBCScriptContextListener[] lc = getListenersCopy();
if (lc != null) {
for (DBCScriptContextListener l : lc) l.variableChanged(contextAction, variableInfo);
}
}
private void notifyListeners(DBCScriptContextListener.ContextAction contextAction, String paramName, Object paramValue) {
DBCScriptContextListener[] lc = getListenersCopy();
if (lc != null) {
for (DBCScriptContextListener l : lc) l.parameterChanged(contextAction, paramName, paramValue);
}
}
}
......@@ -28,9 +28,7 @@ import org.jkiss.utils.xml.XMLException;
import org.xml.sax.Attributes;
import java.io.*;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.*;
public class SQLQueryParameterRegistry
{
......@@ -60,11 +58,15 @@ public class SQLQueryParameterRegistry
{
if (registry == null) {
registry = new SQLQueryParameterRegistry();
registry.loadProfiles();
registry.loadParameters();
}
return registry;
}
public List<ParameterInfo> getAllParameters() {
return new ArrayList<>(parameterMap.values());
}
public ParameterInfo getParameter(String name)
{
return parameterMap.get(name.toUpperCase(Locale.ENGLISH));
......@@ -75,7 +77,7 @@ public class SQLQueryParameterRegistry
parameterMap.put(name.toUpperCase(Locale.ENGLISH), new ParameterInfo(name, value));
}
private void loadProfiles()
private void loadParameters()
{
File storeFile = DBWorkbench.getPlatform().getConfigurationFile(CONFIG_FILE_NAME);
if (!storeFile.exists()) {
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2021 DBeaver Corp and others
*
* 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.model.sql.registry;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.data.json.JSONUtils;
import org.jkiss.dbeaver.model.exec.DBCScriptContext;
import org.jkiss.dbeaver.model.runtime.AbstractJob;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.sql.internal.SQLModelActivator;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.utils.CommonUtils;
import org.jkiss.utils.IOUtils;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
public class SQLVariablesRegistry {
private static final Log log = Log.getLog(SQLVariablesRegistry.class);
public static final String CONFIG_FILE_PREFIX = "sql-variables-"; //$NON-NLS-1$
public static final String CONFIG_FILE_SUFFIX = ".json"; //$NON-NLS-1$
public static final String CONFIG_FILE_TYPE_DRIVER = "driver"; //$NON-NLS-1$
public static final String CONFIG_FILE_TYPE_CONNECTION = "con"; //$NON-NLS-1$
public static final String VARIABLES_STORE_DIR = "variables";
private static final Gson CONFIG_GSON = new GsonBuilder()
.setLenient()
.serializeNulls()
.setPrettyPrinting()
.create();
private static SQLVariablesRegistry registry;
private final Map<DBPDriver, List<DBCScriptContext.VariableInfo>> driverVariables = new HashMap<>();
private final Map<String, List<DBCScriptContext.VariableInfo>> connectionVariables = new HashMap<>();
private ConfigSaver configSaver;
private final List<Object> saveLock = new ArrayList<>();
private SQLVariablesRegistry() {
}
public static synchronized SQLVariablesRegistry getInstance() {
if (registry == null) {
registry = new SQLVariablesRegistry();
registry.loadVariables();
}
return registry;
}
private void loadVariables() {
File configLocation = getConfigLocation();
File[] configFiles = configLocation.listFiles((dir, name) -> name.startsWith(CONFIG_FILE_PREFIX));
if (configFiles == null) {
return;
}
for (File configFile : configFiles) {
String configName = configFile.getName();
if (!configName.endsWith(CONFIG_FILE_SUFFIX)) {
log.debug("Skip variables config: bad file extension (" + configFile.getAbsolutePath() + ")");
continue;
}
// configName = configName.substring(CONFIG_FILE_PREFIX.length(), configName.length() - CONFIG_FILE_SUFFIX.length());
// String driverId = null, conId = null;
// if (configName.startsWith(CONFIG_FILE_TYPE_DRIVER)) {
// driverId = configName.substring(CONFIG_FILE_TYPE_DRIVER.length() + 1);
// } else if (configName.startsWith(CONFIG_FILE_TYPE_CONNECTION)) {
// conId = configName.substring(CONFIG_FILE_TYPE_DRIVER.length() + 1);
// } else {
// log.debug("Skip variables config: unrecognized variables target (" + configFile.getAbsolutePath() + ")");
// continue;
// }
loadVariablesFromFile(configFile);
}
}
private void loadVariablesFromFile(File file) {
try (InputStream is = new FileInputStream(file)) {
try (Reader r = new InputStreamReader(is, StandardCharsets.UTF_8)) {
Map<String, Object> map = JSONUtils.parseMap(CONFIG_GSON, r);
String driverId = JSONUtils.getString(map, "driver");
String dataSourceId = JSONUtils.getString(map, "datasource");
Map<String, Object> varSrc = JSONUtils.getObject(map, "variables");
List<DBCScriptContext.VariableInfo> variables = new ArrayList<>();
for (Map.Entry<String, Object> entry : varSrc.entrySet()) {
DBCScriptContext.VariableInfo variableInfo;
if (entry.getValue() instanceof Map) {
Map<String, Object> valueMap = (Map<String, Object>) entry.getValue();
Object value = valueMap.get("value");
String type = JSONUtils.getString(valueMap, "type");
if (value == null || type == null) {
log.debug("Invalid variable declaration (" + entry.getKey() + ")");
continue;
}
variableInfo = new DBCScriptContext.VariableInfo(
entry.getKey(),
value,
CommonUtils.valueOf(DBCScriptContext.VariableType.class, type, DBCScriptContext.VariableType.VARIABLE));
} else {
variableInfo = new DBCScriptContext.VariableInfo(
entry.getKey(),
entry.getValue(),
DBCScriptContext.VariableType.VARIABLE);
}
variables.add(variableInfo);
}
// Map<String, DBCScriptContext.VariableInfo> varMap = new LinkedHashMap<>();
// for (DBCScriptContext.VariableInfo v : variables) {
// varMap.put(v.name, v);
// }
if (driverId != null) {
DBPDriver driver = DBWorkbench.getPlatform().getDataSourceProviderRegistry().findDriver(driverId);
if (driver == null) {
log.debug("Driver '" + driverId + "' not found. Saved variables ignored (" + file.getAbsolutePath() + ")");
} else {
this.driverVariables.put(driver, variables);
}
} else if (dataSourceId != null) {
this.connectionVariables.put(dataSourceId, variables);
}
}
} catch (IOException e) {
log.error(e);
}
}
private File getConfigLocation() {
return new File(SQLModelActivator.getInstance().getStateLocation().toFile(), VARIABLES_STORE_DIR);
}
@NotNull
public List<DBCScriptContext.VariableInfo> getDriverVariables(DBPDriver driver) {
List<DBCScriptContext.VariableInfo> variables = driverVariables.get(driver);
return variables == null ? Collections.emptyList() : new ArrayList<>(variables);
}
@NotNull
public List<DBCScriptContext.VariableInfo> getDataSourceVariables(DBPDataSourceContainer dataSource) {
List<DBCScriptContext.VariableInfo> variables = connectionVariables.get(dataSource);
if (variables == null) {
return getDriverVariables(dataSource.getDriver());
}
List<DBCScriptContext.VariableInfo> result = new ArrayList<>(variables);
result.addAll(getDriverVariables(dataSource.getDriver()));
return result;
}
public void updateVariables(
@Nullable DBPDriver driver,
@Nullable DBPDataSourceContainer dataSource,
@NotNull List<DBCScriptContext.VariableInfo> variables)
{
if (dataSource != null) {
List<DBCScriptContext.VariableInfo> vars = connectionVariables.get(dataSource.getId());
if (vars == null) {
connectionVariables.put(dataSource.getId(), new ArrayList<>(variables));
} else {
vars.addAll(variables);
}
} else if (driver != null) {
List<DBCScriptContext.VariableInfo> vars = driverVariables.get(driver.getId());
if (vars == null) {
driverVariables.put(driver, new ArrayList<>(variables));
} else {
vars.addAll(variables);
}
}
saveConfig(driver, dataSource);
}
void saveConfig(@Nullable DBPDriver driver,
@Nullable DBPDataSourceContainer dataSource)
{
synchronized (saveLock) {
if (configSaver != null) {
configSaver.cancel();
configSaver = null;
}
if (driver != null && !saveLock.contains(driver)) saveLock.add(driver);
if (dataSource != null && !saveLock.contains(dataSource)) saveLock.add(dataSource);
configSaver = new ConfigSaver();
configSaver.schedule(1000);
}
}
private class ConfigSaver extends AbstractJob {
ConfigSaver() {
super("Tab folders configuration save");
setSystem(true);
}
@Override
protected IStatus run(DBRProgressMonitor monitor) {
List<Object> toSave;
synchronized (saveLock) {
toSave = new ArrayList<>(saveLock);
saveLock.clear();
}
flushConfig(toSave);
return Status.OK_STATUS;
}
private void flushConfig(List<Object> toSave) {
File configLocation = getConfigLocation();
if (!configLocation.exists()) {
if (!configLocation.mkdirs()) {
log.error("Error creating variables storage location: " + configLocation.getAbsolutePath());
return;
}
}
for (Object so : toSave) {
DBPDriver driver = null;
DBPDataSourceContainer con = null;
String fileName;
if (so instanceof DBPDriver) {
driver = (DBPDriver) so;
fileName = CONFIG_FILE_PREFIX + CONFIG_FILE_TYPE_DRIVER + "-" + driver.getFullId() + CONFIG_FILE_SUFFIX;
} else if (so instanceof DBPDataSourceContainer) {
con = (DBPDataSourceContainer)so;
fileName = CONFIG_FILE_PREFIX + CONFIG_FILE_TYPE_CONNECTION + "-" + ((DBPDataSourceContainer) so).getId() + CONFIG_FILE_SUFFIX;
} else {
continue;
}
fileName = CommonUtils.escapeFileName(fileName);
File configFile = new File(configLocation, fileName);
saveConfigToFile(configFile, driver, con);
}
}
private void saveConfigToFile(File configFile, DBPDriver driver, DBPDataSourceContainer con) {
Map<String, Object> map = new LinkedHashMap<>();
List<DBCScriptContext.VariableInfo> variables;
if (driver != null) {
map.put("driver", driver.getFullId());
variables = driverVariables.get(driver);
} else if (con != null) {
map.put("datasource", con.getId());
variables = connectionVariables.get(con.getId());
} else {
log.debug("Both driver and connection are null");
return;
}
if (CommonUtils.isEmpty(variables)) {
return;
}
Map<String, Object> varMap = new LinkedHashMap<>();
for (DBCScriptContext.VariableInfo v : variables) {
if (v.type == DBCScriptContext.VariableType.VARIABLE) {
varMap.put(v.name, v.value);
} else {
Map<String, Object> varDetails = new LinkedHashMap<>();
varDetails.put("type", v.type.name());
varDetails.put("value", v.value);
varMap.put(v.name, varDetails);
}
}
map.put("variables", varMap);
try {
IOUtils.writeFileFromString(configFile, CONFIG_GSON.toJson(map, Map.class));
} catch (IOException e) {
log.error(e);
}
}
}
}
......@@ -37,6 +37,7 @@ public class DBDAttributeConstraint extends DBDAttributeConstraintBase {
private DBSAttributeBase attribute;
private String attributeName;
private int originalVisualPosition;
private boolean plainNameReference; // Disables ordering by column index
public DBDAttributeConstraint(@NotNull DBDAttributeBinding attribute) {
setAttribute(attribute);
......@@ -90,6 +91,15 @@ public class DBDAttributeConstraint extends DBDAttributeConstraintBase {
return originalVisualPosition;
}
// Disables ordering by column index
public boolean isPlainNameReference() {
return plainNameReference;
}
public void setPlainNameReference(boolean plainNameReference) {
this.plainNameReference = plainNameReference;
}
@Override
public boolean hasFilter() {
return super.hasFilter() || // compare visual position only if it explicitly set
......@@ -142,4 +152,5 @@ public class DBDAttributeConstraint extends DBDAttributeConstraintBase {
return isVisible() == constraint.isVisible() && getVisualPosition() == constraint.getVisualPosition() &&
Arrays.equals(getOptions(), constraint.getOptions());
}
}
......@@ -17,6 +17,7 @@
package org.jkiss.dbeaver.model.exec;
import java.io.PrintWriter;
import java.util.List;
/**
* Script context.
......@@ -24,6 +25,34 @@ import java.io.PrintWriter;
*/
public interface DBCScriptContext {
enum VariableType {
PARAMETER("Parameter"),
VARIABLE("Variable"),
QUERY("Query");
private final String title;
VariableType(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}
class VariableInfo {
public String name;
public Object value;
public VariableType type;
public VariableInfo(String name, Object value, VariableType type) {
this.name = name;
this.value = value;
this.type = type;
}
}
boolean hasVariable(String name);
Object getVariable(String name);
......@@ -32,10 +61,16 @@ public interface DBCScriptContext {
void removeVariable(String name);
List<VariableInfo> getVariables();
<T> T getData(String key);
void setData(String key, Object value);
PrintWriter getOutputWriter();
void addListener(DBCScriptContextListener listener);
void removeListener(DBCScriptContextListener listener);
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2021 DBeaver Corp and others
*
* 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.model.exec;
/**
* Script context listener.
*/
public interface DBCScriptContextListener {
enum ContextAction {
ADD,
UPDATE,
DELETE
}
void variableChanged(ContextAction action, DBCScriptContext.VariableInfo variable);
void parameterChanged(ContextAction action, String name, Object value);
}
......@@ -486,7 +486,7 @@ public final class SQLUtils {
for (DBDAttributeConstraint co : filter.getOrderConstraints()) {
if (hasOrder) query.append(',');
String orderString = null;
if (co.getAttribute() == null || co.getAttribute() instanceof DBDAttributeBindingMeta || co.getAttribute() instanceof DBDAttributeBindingType) {
if (co.isPlainNameReference() || co.getAttribute() == null || co.getAttribute() instanceof DBDAttributeBindingMeta || co.getAttribute() instanceof DBDAttributeBindingType) {
String orderColumn = co.getAttributeName();
if (co.getAttribute() == null || PATTERN_SIMPLE_NAME.matcher(orderColumn).matches()) {
// It is a simple column.
......
......@@ -74,12 +74,12 @@ class DataSourceSerializerModern implements DataSourceSerializer
private static final Log log = Log.getLog(DataSourceSerializerModern.class);
private static final String NODE_CONNECTION = "#connection";
private static Gson CONFIG_GSON = new GsonBuilder()
private static final Gson CONFIG_GSON = new GsonBuilder()
.setLenient()
.serializeNulls()
.setPrettyPrinting()
.create();
private static Gson SECURE_GSON = new GsonBuilder()
private static final Gson SECURE_GSON = new GsonBuilder()
.setLenient()
.serializeNulls()
.create();
......@@ -92,7 +92,7 @@ class DataSourceSerializerModern implements DataSourceSerializer
// 0 level: datasource ID
// 1 level: object type (connection or handler id)
// 2 level: map of secured properties
private Map<String, Map<String, Map<String, String>>> secureProperties = new LinkedHashMap<>();
private final Map<String, Map<String, Map<String, String>>> secureProperties = new LinkedHashMap<>();
DataSourceSerializerModern(DataSourceRegistry registry) {
this.registry = registry;
......
......@@ -93,6 +93,10 @@ command.org.jkiss.dbeaver.ui.editors.sql.show.output.name=Show server output
command.org.jkiss.dbeaver.ui.editors.sql.show.output.description=Show server output console
command.org.jkiss.dbeaver.ui.editors.sql.show.log.name=Show execution log
command.org.jkiss.dbeaver.ui.editors.sql.show.log.description=Show SQL execution log
command.org.jkiss.dbeaver.ui.editors.sql.show.variables.name=Show SQL variables
command.org.jkiss.dbeaver.ui.editors.sql.show.variables.description=Show active SQL variables
command.org.jkiss.dbeaver.ui.editors.sql.toggle.extraPanel.name=Show panels in result tabs
command.org.jkiss.dbeaver.ui.editors.sql.toggle.extraPanel.description=Show panels in result tabs instead of SQL editor pane
command.org.jkiss.dbeaver.ui.editors.sql.toggle.result.panel.name=Toggle results panel
command.org.jkiss.dbeaver.ui.editors.sql.toggle.result.panel.description=Show/hide results panel
......@@ -141,6 +145,7 @@ menu.sqleditor=&SQL Editor
menu.org.jkiss.dbeaver.ui.editors.sql.SQLEditor.execute.label = Execute
menu.org.jkiss.dbeaver.ui.editors.sql.SQLEditor.file.label = File
menu.org.jkiss.dbeaver.ui.editors.sql.SQLEditor.layout.label = Layout
menu.org.jkiss.dbeaver.ui.editors.sql.SQLEditor.extraPanels.label = Panels
themeElementCategory.org.jkiss.dbeaver.ui.presentation.sql.label = SQL Editor
themeElementCategory.org.jkiss.dbeaver.ui.presentation.sql.description = SQL Editor
......
......@@ -234,8 +234,12 @@
<command id="org.jkiss.dbeaver.ui.editors.sql.run.expression" name="%command.org.jkiss.dbeaver.ui.editors.sql.run.expression.name" description="%command.org.jkiss.dbeaver.ui.editors.sql.run.expression.description" categoryId="org.jkiss.dbeaver.core.sql"/>
<command id="org.jkiss.dbeaver.ui.editors.sql.query.next" name="%command.org.jkiss.dbeaver.ui.editors.sql.query.next.name" description="%command.org.jkiss.dbeaver.ui.editors.sql.query.next.description" categoryId="org.jkiss.dbeaver.core.sql"/>
<command id="org.jkiss.dbeaver.ui.editors.sql.query.prev" name="%command.org.jkiss.dbeaver.ui.editors.sql.query.prev.name" description="%command.org.jkiss.dbeaver.ui.editors.sql.query.prev.description" categoryId="org.jkiss.dbeaver.core.sql"/>
<command id="org.jkiss.dbeaver.ui.editors.sql.show.output" name="%command.org.jkiss.dbeaver.ui.editors.sql.show.output.name" description="%command.org.jkiss.dbeaver.ui.editors.sql.show.output.description" categoryId="org.jkiss.dbeaver.core.sql"/>
<command id="org.jkiss.dbeaver.ui.editors.sql.show.log" name="%command.org.jkiss.dbeaver.ui.editors.sql.show.log.name" description="%command.org.jkiss.dbeaver.ui.editors.sql.show.log.description" categoryId="org.jkiss.dbeaver.core.sql"/>
<command id="org.jkiss.dbeaver.ui.editors.sql.show.variables" name="%command.org.jkiss.dbeaver.ui.editors.sql.show.variables.name" description="%command.org.jkiss.dbeaver.ui.editors.sql.show.variables.description" categoryId="org.jkiss.dbeaver.core.sql"/>
<command id="org.jkiss.dbeaver.ui.editors.sql.toggle.extraPanels" name="%command.org.jkiss.dbeaver.ui.editors.sql.toggle.extraPanel.name" description="%command.org.jkiss.dbeaver.ui.editors.sql.toggle.extraPanel.description" categoryId="org.jkiss.dbeaver.core.sql"/>
<command id="org.jkiss.dbeaver.ui.editors.sql.toggle.result.panel" name="%command.org.jkiss.dbeaver.ui.editors.sql.toggle.result.panel.name" description="%command.org.jkiss.dbeaver.ui.editors.sql.toggle.result.panel.description" categoryId="org.jkiss.dbeaver.core.sql"/>
<command id="org.jkiss.dbeaver.ui.editors.sql.maximize.result.panel" name="%command.org.jkiss.dbeaver.ui.editors.sql.maximize.result.panel.name" description="%command.org.jkiss.dbeaver.ui.editors.sql.maximize.result.panel.description" categoryId="org.jkiss.dbeaver.core.sql"/>
<command id="org.jkiss.dbeaver.ui.editors.sql.switch.panel" name="%command.org.jkiss.dbeaver.ui.editors.sql.switch.panel.name" description="%command.org.jkiss.dbeaver.ui.editors.sql.switch.panel.description" categoryId="org.jkiss.dbeaver.core.sql"/>
......@@ -282,6 +286,7 @@
<image commandId="org.jkiss.dbeaver.ui.editors.sql.show.output" icon="platform:/plugin/org.jkiss.dbeaver.ui/icons/sql/page_output.png"/>
<image commandId="org.jkiss.dbeaver.ui.editors.sql.show.log" icon="platform:/plugin/org.jkiss.dbeaver.ui/icons/sql/page_error.png"/>
<image commandId="org.jkiss.dbeaver.ui.editors.sql.show.variables" icon="platform:/plugin/org.jkiss.dbeaver.ui/icons/sql/variables.png"/>
<image commandId="org.jkiss.dbeaver.ui.editors.sql.toggleLayout" icon="platform:/plugin/org.jkiss.dbeaver.ui/icons/misc/rotate.png"/>
</extension>
......@@ -457,6 +462,13 @@
<handler commandId="org.jkiss.dbeaver.ui.editors.sql.show.log" class="org.jkiss.dbeaver.ui.editors.sql.handlers.SQLEditorHandlerSwitchPanel">
<enabledWhen><reference definitionId="org.jkiss.dbeaver.core.ui.sql.editor"/></enabledWhen>
</handler>
<handler commandId="org.jkiss.dbeaver.ui.editors.sql.show.variables" class="org.jkiss.dbeaver.ui.editors.sql.handlers.SQLEditorHandlerSwitchPanel">
<enabledWhen><reference definitionId="org.jkiss.dbeaver.core.ui.sql.editor"/></enabledWhen>
</handler>
<handler commandId="org.jkiss.dbeaver.ui.editors.sql.toggle.extraPanels" class="org.jkiss.dbeaver.ui.editors.sql.handlers.SQLEditorHandlerToggleExtraPanels">
<enabledWhen><reference definitionId="org.jkiss.dbeaver.core.ui.sql.editor"/></enabledWhen>
</handler>
<handler commandId="org.jkiss.dbeaver.ui.editors.sql.toggle.result.panel" class="org.jkiss.dbeaver.ui.editors.sql.handlers.SQLEditorHandlerToggleResultsPanel">
<enabledWhen><reference definitionId="org.jkiss.dbeaver.core.ui.sql.editor"/></enabledWhen>
</handler>
......@@ -832,11 +844,23 @@
</with>
</visibleWhen>
</command>
<separator name="layout" visible="true"/>
<command commandId="org.jkiss.dbeaver.ui.editors.sql.toggle.result.panel"/>
<command commandId="org.jkiss.dbeaver.ui.editors.sql.maximize.result.panel" style="push"/>
<command commandId="org.jkiss.dbeaver.ui.editors.sql.switch.panel"/>
<menu label="%menu.org.jkiss.dbeaver.ui.editors.sql.SQLEditor.extraPanels.label">
<command commandId="org.jkiss.dbeaver.ui.editors.sql.show.output"/>
<command commandId="org.jkiss.dbeaver.ui.editors.sql.show.log"/>
<command commandId="org.jkiss.dbeaver.ui.editors.sql.show.variables"/>
<separator name="panels_config" visible="true"/>
<command commandId="org.jkiss.dbeaver.ui.editors.sql.toggle.extraPanels" style="toggle"/>
</menu>
<menu label="%menu.org.jkiss.dbeaver.ui.editors.sql.SQLEditor.layout.label">
<dynamic id="org.jkiss.dbeaver.ui.editors.sql.SQLEditor.layout.resultSet.orientation" class="org.jkiss.dbeaver.ui.editors.sql.SQLEditor$ResultSetOrientationMenuContributor"/>
<separator name="layout_toggles" visible="true"/>
<command commandId="org.jkiss.dbeaver.ui.editors.sql.toggle.result.panel"/>
<command commandId="org.jkiss.dbeaver.ui.editors.sql.maximize.result.panel"/>
<command commandId="org.jkiss.dbeaver.ui.editors.sql.switch.panel"/>
</menu>
<separator name="context" visible="true"/>
......@@ -891,6 +915,15 @@
<command commandId="org.jkiss.dbeaver.ui.editors.sql.switch.panel"/>
</menu>
</menuContribution>
<menuContribution allPopups="false" locationURI="popup:org.jkiss.dbeaver.ui.editors.sql.SQLEditor.EditorContext?after=sql.extras">
<menu id="org.jkiss.dbeaver.ui.editors.sql.SQLEditor.extraPanels" label="%menu.org.jkiss.dbeaver.ui.editors.sql.SQLEditor.extraPanels.label">
<command commandId="org.jkiss.dbeaver.ui.editors.sql.show.output"/>
<command commandId="org.jkiss.dbeaver.ui.editors.sql.show.log"/>
<command commandId="org.jkiss.dbeaver.ui.editors.sql.show.variables"/>
<separator name="panels_config" visible="true"/>
<command commandId="org.jkiss.dbeaver.ui.editors.sql.toggle.extraPanels" style="toggle"/>
</menu>
</menuContribution>
<menuContribution allPopups="false" locationURI="popup:org.jkiss.dbeaver.ui.editors.sql.SQLEditor.EditorContext?after=group.copy">
<command commandId="org.jkiss.dbeaver.core.edit.copy.special"/>
</menuContribution>
......
......@@ -43,6 +43,7 @@ import org.eclipse.swt.widgets.*;
import org.eclipse.ui.*;
import org.eclipse.ui.actions.CompoundContributionItem;
import org.eclipse.ui.ide.FileStoreEditorInput;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.texteditor.DefaultRangeIndicator;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
import org.eclipse.ui.texteditor.rulers.IColumnSupport;
......@@ -101,6 +102,7 @@ import org.jkiss.dbeaver.ui.editors.sql.plan.ExplainPlanViewer;
import org.jkiss.dbeaver.ui.editors.sql.registry.SQLPresentationDescriptor;
import org.jkiss.dbeaver.ui.editors.sql.registry.SQLPresentationPanelDescriptor;
import org.jkiss.dbeaver.ui.editors.sql.registry.SQLPresentationRegistry;
import org.jkiss.dbeaver.ui.editors.sql.variables.SQLVariablesPanel;
import org.jkiss.dbeaver.ui.editors.text.ScriptPositionColumn;
import org.jkiss.dbeaver.ui.navigator.INavigatorModelView;
import org.jkiss.dbeaver.utils.GeneralUtils;
......@@ -140,12 +142,13 @@ public class SQLEditor extends SQLEditorBase implements
private static final String EMBEDDED_BINDING_PREFIX = "-- CONNECTION: ";
private static final Pattern EMBEDDED_BINDING_PREFIX_PATTERN = Pattern.compile("--\\s*CONNECTION:\\s*(.+)", Pattern.CASE_INSENSITIVE);
private static Image IMG_DATA_GRID = DBeaverIcons.getImage(UIIcon.SQL_PAGE_DATA_GRID);
private static Image IMG_DATA_GRID_LOCKED = DBeaverIcons.getImage(UIIcon.SQL_PAGE_DATA_GRID_LOCKED);
private static Image IMG_EXPLAIN_PLAN = DBeaverIcons.getImage(UIIcon.SQL_PAGE_EXPLAIN_PLAN);
private static Image IMG_LOG = DBeaverIcons.getImage(UIIcon.SQL_PAGE_LOG);
private static Image IMG_OUTPUT = DBeaverIcons.getImage(UIIcon.SQL_PAGE_OUTPUT);
private static Image IMG_OUTPUT_ALERT = DBeaverIcons.getImage(UIIcon.SQL_PAGE_OUTPUT_ALERT);
private static final Image IMG_DATA_GRID = DBeaverIcons.getImage(UIIcon.SQL_PAGE_DATA_GRID);
private static final Image IMG_DATA_GRID_LOCKED = DBeaverIcons.getImage(UIIcon.SQL_PAGE_DATA_GRID_LOCKED);
private static final Image IMG_EXPLAIN_PLAN = DBeaverIcons.getImage(UIIcon.SQL_PAGE_EXPLAIN_PLAN);
private static final Image IMG_LOG = DBeaverIcons.getImage(UIIcon.SQL_PAGE_LOG);
private static final Image IMG_VARIABLES = DBeaverIcons.getImage(UIIcon.SQL_VARIABLES);
private static final Image IMG_OUTPUT = DBeaverIcons.getImage(UIIcon.SQL_PAGE_OUTPUT);
private static final Image IMG_OUTPUT_ALERT = DBeaverIcons.getImage(UIIcon.SQL_PAGE_OUTPUT_ALERT);
// private static final String TOOLBAR_CONTRIBUTION_ID = "toolbar:org.jkiss.dbeaver.ui.editors.sql.toolbar.side";
// private static final String TOOLBAR_GROUP_TOP = "top";
......@@ -176,6 +179,7 @@ public class SQLEditor extends SQLEditorBase implements
private SQLLogPanel logViewer;
private SQLEditorOutputConsoleViewer outputViewer;
private SQLVariablesPanel variablesViewer;
private volatile QueryProcessor curQueryProcessor;
private final List<QueryProcessor> queryProcessors = new ArrayList<>();
......@@ -270,6 +274,10 @@ public class SQLEditor extends SQLEditorBase implements
return null;
}
public SQLScriptContext getGlobalScriptContext() {
return globalScriptContext;
}
@Nullable
public DBPProject getProject()
{
......@@ -911,15 +919,19 @@ public class SQLEditor extends SQLEditorBase implements
SWT.LEFT | SWT.CHECK,
getSite(),
SQLEditorCommands.CMD_SQL_SHOW_OUTPUT,
true)
.setText("Out");
false);
VerticalButton.create(
sideToolBar,
SWT.LEFT | SWT.CHECK,
getSite(),
SQLEditorCommands.CMD_SQL_SHOW_LOG,
true)
.setText("Log");
false);
VerticalButton.create(
sideToolBar,
SWT.LEFT | SWT.CHECK,
getSite(),
SQLEditorCommands.CMD_SQL_SHOW_VARIABLES,
false);
/*
sideToolBar.add(new GroupMarker(TOOLBAR_GROUP_PANELS));
......@@ -1073,9 +1085,7 @@ public class SQLEditor extends SQLEditorBase implements
});
// Extra views
//planView = new ExplainPlanViewer(this, resultTabs);
logViewer = new SQLLogPanel(sqlExtraPanelFolder, this);
outputViewer = new SQLEditorOutputConsoleViewer(getSite(), sqlExtraPanelFolder, SWT.NONE);
createExtraViewControls();
// Create results tab
createQueryProcessor(true, true);
......@@ -1260,24 +1270,110 @@ public class SQLEditor extends SQLEditorBase implements
/////////////////////////////////////////////////////////////
// Panels
public void toggleExtraPanelsLayout() {
CTabItem outTab = getExtraViewTab(outputViewer.getControl());
CTabItem logTab = getExtraViewTab(logViewer);
CTabItem varTab = getExtraViewTab(variablesViewer);
if (outTab != null) outTab.dispose();
if (logTab != null) logTab.dispose();
if (varTab != null) varTab.dispose();
IPreferenceStore preferenceStore = getPreferenceStore();
String epLocation = getExtraPanelsLocation();
if (SQLPreferenceConstants.LOCATION_RESULTS.equals(epLocation)) {
epLocation = SQLPreferenceConstants.LOCATION_RIGHT;
} else {
epLocation = SQLPreferenceConstants.LOCATION_RESULTS;
}
preferenceStore.setValue(SQLPreferenceConstants.EXTRA_PANEL_LOCATION, epLocation);
createExtraViewControls();
if (outTab != null) showOutputPanel();
if (logTab != null) showExecutionLogPanel();
if (varTab != null) showVariablesPanel();
}
public String getExtraPanelsLocation() {
return getPreferenceStore().getString(SQLPreferenceConstants.EXTRA_PANEL_LOCATION);
}
private void createExtraViewControls() {
if (logViewer != null) {
logViewer.dispose();
logViewer = null;
}
if (variablesViewer != null) {
variablesViewer.dispose();
variablesViewer = null;
}
if (outputViewer != null) {
outputViewer.dispose();
outputViewer = null;
}
if (sqlExtraPanelFolder != null) {
for (CTabItem ti : sqlExtraPanelFolder.getItems()) {
ti.dispose();
}
}
//planView = new ExplainPlanViewer(this, resultTabs);
CTabFolder folder = getFolderForExtraPanels();
logViewer = new SQLLogPanel(folder, this);
variablesViewer = new SQLVariablesPanel(folder, this);
outputViewer = new SQLEditorOutputConsoleViewer(getSite(), folder, SWT.NONE);
if (getFolderForExtraPanels() != sqlExtraPanelFolder) {
sqlExtraPanelSash.setMaximizedControl(sqlExtraPanelSash.getChildren()[0]);
}
}
private CTabFolder getFolderForExtraPanels() {
CTabFolder folder = this.sqlExtraPanelFolder;
String epLocation = getExtraPanelsLocation();
if (SQLPreferenceConstants.LOCATION_RESULTS.equals(epLocation)) {
folder = resultTabs;
}
return folder;
}
private CTabItem getExtraViewTab(Control control) {
CTabFolder tabFolder = this.getFolderForExtraPanels();
for (CTabItem item : tabFolder.getItems()) {
if (item.getData() == control) {
return item;
}
}
return null;
}
private void showExtraView(final String commandId, String name, String toolTip, Image image, Control view, IActionContributor actionContributor) {
VerticalButton viewItem = getViewToolItem(commandId);
if (viewItem == null) {
log.warn("Tool item for command " + commandId + " not found");
return;
}
for (CTabItem item : sqlExtraPanelFolder.getItems()) {
if (item.getData() == view) {
// Close tab if it is already open
viewItem.setChecked(false);
viewItem.redraw();
item.dispose();
return;
}
CTabFolder tabFolder = this.getFolderForExtraPanels();
CTabItem curItem = getExtraViewTab(view);
if (curItem != null) {
// Close tab if it is already open
viewItem.setChecked(false);
viewItem.redraw();
curItem.dispose();
return;
}
if (sqlExtraPanelSash.getMaximizedControl() != null) {
sqlExtraPanelSash.setMaximizedControl(null);
boolean isTabsToTheRight = tabFolder == sqlExtraPanelFolder;
if (isTabsToTheRight) {
if (sqlExtraPanelSash.getMaximizedControl() != null) {
sqlExtraPanelSash.setMaximizedControl(null);
}
} else {
sqlExtraPanelSash.setMaximizedControl(sqlExtraPanelSash.getChildren()[0]);
// Show results
showResultsPanel();
}
if (view == outputViewer.getControl()) {
......@@ -1287,7 +1383,7 @@ public class SQLEditor extends SQLEditorBase implements
// Create new tab
viewItem.setChecked(true);
CTabItem item = new CTabItem(sqlExtraPanelFolder, SWT.CLOSE);
CTabItem item = new CTabItem(tabFolder, SWT.CLOSE);
item.setControl(view);
item.setText(name);
item.setToolTipText(toolTip);
......@@ -1300,14 +1396,16 @@ public class SQLEditor extends SQLEditorBase implements
viewItem.setChecked(false);
viewItem.redraw();
}
if (sqlExtraPanelFolder.getItemCount() == 0) {
if (tabFolder.getItemCount() == 0) {
sqlExtraPanelSash.setMaximizedControl(sqlExtraPanelSash.getChildren()[0]);
}
});
sqlExtraPanelFolder.setSelection(item);
tabFolder.setSelection(item);
viewItem.redraw();
updateExtraViewToolbar(actionContributor);
if (isTabsToTheRight) {
updateExtraViewToolbar(actionContributor);
}
}
private void updateExtraViewToolbar(IActionContributor actionContributor) {
......@@ -1316,6 +1414,11 @@ public class SQLEditor extends SQLEditorBase implements
if (actionContributor != null) {
actionContributor.contributeActions(sqlExtraPanelToolbar);
}
sqlExtraPanelToolbar.add(ActionUtils.makeCommandContribution(
getSite(),
"org.jkiss.dbeaver.ui.editors.sql.toggle.extraPanels",
CommandContributionItem.STYLE_CHECK,
UIIcon.ARROW_DOWN));
sqlExtraPanelToolbar.update(true);
}
......@@ -1350,9 +1453,7 @@ public class SQLEditor extends SQLEditorBase implements
SQLEditorMessages.editors_sql_output_tip,
IMG_OUTPUT,
outputViewer.getControl(),
manager -> {
manager.add(new OutputAutoShowToggleAction());
});
manager -> manager.add(new OutputAutoShowToggleAction()));
}
public void showExecutionLogPanel() {
......@@ -1365,6 +1466,17 @@ public class SQLEditor extends SQLEditorBase implements
null);
}
public void showVariablesPanel() {
showExtraView(
SQLEditorCommands.CMD_SQL_SHOW_VARIABLES,
SQLEditorMessages.editors_sql_variables,
SQLEditorMessages.editors_sql_variables_tip,
IMG_VARIABLES,
variablesViewer,
null);
UIUtils.asyncExec(() -> variablesViewer.refreshVariables());
}
public <T> T getExtraPresentationPanel(Class<T> panelClass) {
for (CTabItem tabItem : resultTabs.getItems()) {
if (tabItem.getData() instanceof SQLEditorPresentationPanel && tabItem.getData().getClass() == panelClass) {
......@@ -1677,6 +1789,30 @@ public class SQLEditor extends SQLEditorBase implements
EditorUtils.getLocalFileFromInput(getEditorInput()),
new OutputLogWriter(),
new SQLEditorParametersProvider(getSite()));
this.globalScriptContext.addListener(new DBCScriptContextListener() {
@Override
public void variableChanged(ContextAction action, DBCScriptContext.VariableInfo variable) {
saveContextVariables();
}
@Override
public void parameterChanged(ContextAction action, String name, Object value) {
saveContextVariables();
}
private void saveContextVariables() {
new AbstractJob("Save variables") {
@Override
protected IStatus run(DBRProgressMonitor monitor) {
DBPDataSourceContainer ds = getDataSourceContainer();
if (ds != null) {
globalScriptContext.saveVariables(ds.getDriver(), null);
}
return Status.OK_STATUS;
}
}.schedule(200);
}
});
}
@Override
......@@ -2357,7 +2493,8 @@ public class SQLEditor extends SQLEditorBase implements
reloadSyntaxRules();
}
if (getDataSourceContainer() == null) {
DBPDataSourceContainer dataSourceContainer = getDataSourceContainer();
if (dataSourceContainer == null) {
resultsSash.setMaximizedControl(sqlEditorPanel);
} else {
if (curQueryProcessor != null && curQueryProcessor.getFirstResults().hasData()) {
......@@ -2369,6 +2506,12 @@ public class SQLEditor extends SQLEditorBase implements
syntaxLoaded = true;
loadActivePreferenceSettings();
if (dataSourceContainer != null) {
globalScriptContext.loadVariables(dataSourceContainer.getDriver(), null);
} else {
globalScriptContext.clearVariables();
}
}
@Override
......
......@@ -41,6 +41,7 @@ public interface SQLEditorCommands
String CMD_SQL_SWITCH_PANEL = "org.jkiss.dbeaver.ui.editors.sql.switch.panel";
String CMD_SQL_SHOW_OUTPUT = "org.jkiss.dbeaver.ui.editors.sql.show.output";
String CMD_SQL_SHOW_LOG = "org.jkiss.dbeaver.ui.editors.sql.show.log";
String CMD_SQL_SHOW_VARIABLES = "org.jkiss.dbeaver.ui.editors.sql.show.variables";
String CMD_SQL_EDITOR_MAXIMIZE_PANEL = "org.jkiss.dbeaver.ui.editors.sql.maximize.result.panel";
String CMD_SQL_EDITOR_CLOSE_TAB = "org.jkiss.dbeaver.ui.editors.sql.close.tab";
String CMD_SQL_ASSIST_TEMPLATES = "org.jkiss.dbeaver.ui.editors.sql.assist.templates"; //$NON-NLS-1$
......
......@@ -82,6 +82,10 @@ public class SQLEditorOutputConsoleViewer extends TextConsoleViewer {
writer = new PrintWriter(out, true);
}
public void dispose() {
this.getControl().dispose();
}
public boolean isDisposed() {
return this.getControl().isDisposed();
}
......
......@@ -116,6 +116,7 @@ public class SQLPreferenceConstants
public final static String RESULT_SET_ORIENTATION = "SQLEditor.resultSet.orientation";
public static final String RESULTS_PANEL_RATIO = "SQLEditor.resultSet.ratio";
public static final String EXTRA_PANEL_RATIO = "SQLEditor.extraPanels.ratio";
public static final String EXTRA_PANEL_LOCATION = "SQLEditor.extraPanels.location";
public static final String OUTPUT_PANEL_AUTO_SHOW = "SQLEditor.outputPanel.autoShow";
public static final String SCRIPT_BIND_EMBEDDED_READ = "SQLEditor.script.bind.embedded.read"; //$NON-NLS-1$
......@@ -144,5 +145,8 @@ public class SQLPreferenceConstants
public static final String DEFAULT_SQL_EDITOR_OPEN_COMMAND = "SQLEditor.defaultOpenCommand";
public static final String LOCATION_RIGHT = "right";
public static final String LOCATION_BOTTOM = "bottom";
public static final String LOCATION_RESULTS = "results";
}
......@@ -48,6 +48,9 @@ public class SQLEditorHandlerSwitchPanel extends AbstractHandler {
case SQLEditorCommands.CMD_SQL_SHOW_LOG:
editor.showExecutionLogPanel();
break;
case SQLEditorCommands.CMD_SQL_SHOW_VARIABLES:
editor.showVariablesPanel();
break;
}
return null;
}
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2021 DBeaver Corp and others
*
* 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.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.commands.IElementUpdater;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.ui.menus.UIElement;
import org.jkiss.dbeaver.ui.editors.sql.SQLEditor;
import org.jkiss.dbeaver.ui.editors.sql.SQLPreferenceConstants;
import org.jkiss.dbeaver.utils.RuntimeUtils;
import java.util.Map;
public class SQLEditorHandlerToggleExtraPanels extends AbstractHandler implements IElementUpdater {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
SQLEditor editor = RuntimeUtils.getObjectAdapter(HandlerUtil.getActiveEditor(event), SQLEditor.class);
if (editor != null) {
editor.toggleExtraPanelsLayout();
}
return null;
}
@Override
public void updateElement(UIElement element, Map parameters) {
IWorkbenchWindow workbenchWindow = element.getServiceLocator().getService(IWorkbenchWindow.class);
IEditorPart activeEditor = workbenchWindow.getActivePage().getActiveEditor();
if (activeEditor instanceof SQLEditor) {
element.setChecked(SQLPreferenceConstants.LOCATION_RESULTS.equals(((SQLEditor) activeEditor).getExtraPanelsLocation()));
}
}
}
\ No newline at end of file
......@@ -65,6 +65,8 @@ public class SQLEditorMessages extends NLS {
public static String editors_sql_error_execution_plan_title;
public static String editors_sql_execution_log;
public static String editors_sql_execution_log_tip;
public static String editors_sql_variables;
public static String editors_sql_variables_tip;
public static String editors_sql_explain_plan;
public static String editors_sql_output;
public static String editors_sql_output_tip;
......
......@@ -41,6 +41,8 @@ editors_sql_error_execution_plan_message = Can not explain execution plan
editors_sql_error_execution_plan_title = Execution plan
editors_sql_execution_log = Execution Log
editors_sql_execution_log_tip = SQL query execution log
editors_sql_variables = Variables
editors_sql_variables_tip = Active SQL variables
editors_sql_explain_plan = Explain Plan
editors_sql_job_execute_query = Execute query
editors_sql_job_execute_script = Execute script
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2021 DBeaver Corp and others
*
* 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.variables;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IContributionManager;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.dialogs.PatternFilter;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
import org.jkiss.dbeaver.model.exec.DBCScriptContext;
import org.jkiss.dbeaver.model.exec.DBCScriptContextListener;
import org.jkiss.dbeaver.model.sql.SQLScriptContext;
import org.jkiss.dbeaver.model.sql.registry.SQLQueryParameterRegistry;
import org.jkiss.dbeaver.ui.*;
import org.jkiss.dbeaver.ui.controls.ListContentProvider;
import org.jkiss.dbeaver.ui.controls.ProgressPageControl;
import org.jkiss.dbeaver.ui.editors.StringEditorInput;
import org.jkiss.dbeaver.ui.editors.SubEditorSite;
import org.jkiss.dbeaver.ui.editors.TextEditorUtils;
import org.jkiss.dbeaver.ui.editors.sql.SQLEditor;
import org.jkiss.dbeaver.ui.editors.sql.SQLEditorBase;
import org.jkiss.dbeaver.utils.GeneralUtils;
import org.jkiss.utils.CommonUtils;
import java.util.List;
import java.util.regex.PatternSyntaxException;
/**
* SQLVariablesPanel
*/
public class SQLVariablesPanel extends Composite implements DBCScriptContextListener {
static protected final Log log = Log.getLog(SQLVariablesPanel.class);
private final SQLEditor mainEditor;
private SQLEditorBase valueEditor;
private TableViewer varsTable;
private boolean showParameters;
public SQLVariablesPanel(Composite parent, SQLEditor editor)
{
super(parent, SWT.NONE);
this.mainEditor = editor;
setLayout(new FillLayout());
}
private void createControls() {
mainEditor.getGlobalScriptContext().addListener(this);
addDisposeListener(e -> mainEditor.getGlobalScriptContext().removeListener(this));
SashForm sash = new SashForm(this, SWT.VERTICAL);
// Variables table
{
VariableListControl variableListControl = new VariableListControl(sash);
variableListControl.createOrSubstituteProgressPanel(mainEditor.getSite());
}
// Editor
{
Composite editorGroup = UIUtils.createPlaceholder(sash, 1);
UIUtils.createControlLabel(editorGroup, "Value");
Composite editorPH = new Composite(editorGroup, SWT.NONE);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.verticalIndent = 3;
gd.horizontalSpan = 1;
gd.minimumHeight = 100;
gd.minimumWidth = 100;
editorPH.setLayoutData(gd);
editorPH.setLayout(new FillLayout());
valueEditor = new SQLEditorBase() {
@Nullable
@Override
public DBCExecutionContext getExecutionContext() {
return mainEditor.getExecutionContext();
}
@Override
public void createPartControl(Composite parent) {
super.createPartControl(parent);
getAction(ITextEditorActionConstants.CONTEXT_PREFERENCES).setEnabled(false);
}
@Override
public boolean isFoldingEnabled() {
return false;
}
};
try {
valueEditor.init(new SubEditorSite(mainEditor.getSite()),
new StringEditorInput("Variable value", "", true, GeneralUtils.getDefaultFileEncoding()));
} catch (PartInitException e) {
log.error(e);
}
valueEditor.createPartControl(editorPH);
valueEditor.reloadSyntaxRules();
//valueEditor.getEditorControl().setEnabled(false);
valueEditor.getEditorControlWrapper().setLayoutData(new GridData(GridData.FILL_BOTH));
}
sash.setWeights(new int[] { 600, 400 });
}
private void editCurrentVariable() {
ISelection selection = varsTable.getSelection();
StyledText editorControl = valueEditor.getEditorControl();
if (editorControl == null) {
return;
}
if (!selection.isEmpty()) {
//TableItem item = varsTable.getItem(selectionIndex);
DBCScriptContext.VariableInfo variable = (DBCScriptContext.VariableInfo) ((IStructuredSelection)selection).getFirstElement();
StringEditorInput sqlInput = new StringEditorInput(
"Variable " + variable.name,
CommonUtils.toString(variable.value),
false,
GeneralUtils.DEFAULT_ENCODING
);
valueEditor.setInput(sqlInput);
valueEditor.reloadSyntaxRules();
}
}
public void refreshVariables() {
if (varsTable == null) {
createControls();
}
SQLScriptContext context = mainEditor.getGlobalScriptContext();
//varsTable.removeAll();
List<DBCScriptContext.VariableInfo> variables = context.getVariables();
if (showParameters) {
for (SQLQueryParameterRegistry.ParameterInfo param : SQLQueryParameterRegistry.getInstance().getAllParameters()) {
if (context.hasVariable(param.name)) {
continue;
}
Object parameterValue = context.getParameterDefaultValue(param.name);
if (parameterValue == null) {
parameterValue = param.value;
}
variables.add(new DBCScriptContext.VariableInfo(
param.name,
parameterValue,
DBCScriptContext.VariableType.PARAMETER));
}
}
varsTable.setInput(variables);
UIUtils.packColumns(varsTable.getTable(), true);
valueEditor.setInput(new StringEditorInput(
"Variable",
"",
true,
GeneralUtils.DEFAULT_ENCODING
));
valueEditor.reloadSyntaxRules();
}
@Override
public void variableChanged(ContextAction action, DBCScriptContext.VariableInfo variable) {
UIUtils.asyncExec(this::refreshVariables);
}
@Override
public void parameterChanged(ContextAction action, String name, Object value) {
UIUtils.asyncExec(this::refreshVariables);
}
private class VariableListControl extends ProgressPageControl {
private final ISearchExecutor searcher;
private Action addAction;
private Action deleteAction;
public VariableListControl(Composite parent) {
super(parent, SWT.SHEET);
searcher = new ISearchExecutor() {
@Override
public boolean performSearch(String searchString, int options) {
try {
PatternFilter searchFilter = new PatternFilter() {
protected boolean isLeafMatch(Viewer viewer, Object element) {
DBCScriptContext.VariableInfo variable = (DBCScriptContext.VariableInfo) element;
return wordMatches(variable.name) || wordMatches(CommonUtils.toString(variable.value));
}
};
searchFilter.setPattern(searchString);
//(options & SEARCH_CASE_SENSITIVE) != 0);
varsTable.setFilters(new ViewerFilter[]{ searchFilter });
return true;
} catch (PatternSyntaxException e) {
log.error(e.getMessage());
return false;
}
}
@Override
public void cancelSearch() {
varsTable.setFilters(new ViewerFilter[0]);
}
};
varsTable = new TableViewer(this, SWT.SINGLE | SWT.FULL_SELECTION);
varsTable.getTable().setHeaderVisible(true);
varsTable.getTable().setLinesVisible(true);
varsTable.getTable().setLayoutData(new GridData(GridData.FILL_BOTH));
UIUtils.createTableColumn(varsTable.getTable(), SWT.LEFT, "Variable");
UIUtils.createTableColumn(varsTable.getTable(), SWT.LEFT, "Value");
UIUtils.createTableColumn(varsTable.getTable(), SWT.LEFT, "Type");
varsTable.setContentProvider(new ListContentProvider());
varsTable.setLabelProvider(new CellLabelProvider() {
@Override
public void update(ViewerCell cell) {
DBCScriptContext.VariableInfo variable = (DBCScriptContext.VariableInfo) cell.getElement();
switch (cell.getColumnIndex()) {
case 0:
cell.setText(variable.name);
break;
case 1:
cell.setText(CommonUtils.toString(variable.value));
break;
case 2:
cell.setText(variable.type.getTitle());
break;
}
}
});
varsTable.addSelectionChangedListener(event -> {
if (deleteAction != null) {
deleteAction.setEnabled(!event.getSelection().isEmpty());
updateActions();
}
editCurrentVariable();
});
}
@Override
protected ISearchExecutor getSearchRunner() {
return searcher;
}
protected void addSearchAction(IContributionManager contributionManager) {
contributionManager.add(new Action("Find variable", DBeaverIcons.getImageDescriptor(UIIcon.SEARCH)) {
@Override
public void run() {
performSearch(SearchType.NONE);
}
});
}
@Override
protected void createSearchControls() {
super.createSearchControls();
Text textControl = getSearchTextControl();
if (textControl != null) {
TextEditorUtils.enableHostEditorKeyBindingsSupport(mainEditor.getSite(), textControl);
}
}
@Override
public void fillCustomActions(IContributionManager contributionManager) {
super.fillCustomActions(contributionManager);
addAction = new Action("Add variable", DBeaverIcons.getImageDescriptor(UIIcon.ADD)) {
@Override
public void run() {
super.run();
}
};
contributionManager.add(addAction);
deleteAction = new Action("Delete variable", DBeaverIcons.getImageDescriptor(UIIcon.DELETE)) {
@Override
public void run() {
super.run();
}
};
deleteAction.setEnabled(false);
contributionManager.add(deleteAction);
Action showParamsAction = new Action("Show parameters", Action.AS_CHECK_BOX) {
@Override
public void run() {
showParameters = !showParameters;
refreshVariables();
}
};
showParamsAction.setChecked(showParameters);
showParamsAction.setImageDescriptor(DBeaverIcons.getImageDescriptor(UIIcon.SQL_VARIABLES));
showParamsAction.setDescription("Show query parameters");
contributionManager.add(ActionUtils.makeActionContribution(showParamsAction, true));
}
}
}
\ No newline at end of file
......@@ -126,7 +126,6 @@ public abstract class ObjectListControl<OBJECT_TYPE> extends ProgressPageControl
}
};
boolean showTableGrid = DBWorkbench.getPlatform().getPreferenceStore().getBoolean(NavigatorPreferences.NAVIGATOR_EDITOR_SHOW_TABLE_GRID);
if (UIStyles.isDarkTheme()) {
// Do not show grid in dark theme. It is awful
......
......@@ -190,6 +190,7 @@ public class UIIcon {
public static final DBIcon SQL_VALIDATE = new DBIcon("sql_validate", "sql/sql_validate.png"); //$NON-NLS-1$ //$NON-NLS-2$
public static final DBIcon SQL_PREVIEW = new DBIcon("sql_preview", "sql/sql_preview.png"); //$NON-NLS-1$ //$NON-NLS-2$
public static final DBIcon SQL_TEXT = new DBIcon("sql_text", "sql/sql_text.png"); //$NON-NLS-1$ //$NON-NLS-2$
public static final DBIcon SQL_VARIABLES = new DBIcon("sql_variables", "sql/variables.png"); //$NON-NLS-1$ //$NON-NLS-2$
public static final DBIcon SQL_PAGE_DATA_GRID = new DBIcon("sql/page_data_grid.png"); //$NON-NLS-1$
public static final DBIcon SQL_PAGE_DATA_GRID_LOCKED = new DBIcon("sql/page_data_grid_locked.png"); //$NON-NLS-1$
......
......@@ -52,7 +52,7 @@ import org.jkiss.utils.CommonUtils;
import java.util.ArrayList;
/**
* ItemListControl
* ProgressPageControl
*/
public class ProgressPageControl extends Composite implements ISearchContextProvider, ICustomActionsProvider
{
......@@ -265,7 +265,7 @@ public class ProgressPageControl extends Composite implements ISearchContextProv
if (searchControlsComposite == null || searchControlsComposite.isDisposed()) {
return;
}
searchControlsComposite.getParent().setRedraw(false);
this.setRedraw(false);
try {
// Delete all controls created in searchControlsComposite
UIUtils.disposeChildControls(searchControlsComposite);
......@@ -302,7 +302,7 @@ public class ProgressPageControl extends Composite implements ISearchContextProv
searchControlsComposite.getParent().layout();
//customControlsComposite.layout();
} finally {
searchControlsComposite.getParent().setRedraw(true);
this.setRedraw(true);
}
}
......@@ -352,7 +352,7 @@ public class ProgressPageControl extends Composite implements ISearchContextProv
searchControlsComposite.getParent().layout();
}
private void createSearchControls()
protected void createSearchControls()
{
if (searchText != null) {
return;
......@@ -360,80 +360,84 @@ public class ProgressPageControl extends Composite implements ISearchContextProv
hideControls(false);
((GridLayout)searchControlsComposite.getLayout()).numColumns = 2;
searchText = new Text(searchControlsComposite, SWT.BORDER);
UIUtils.addDefaultEditActionsSupport(UIUtils.getActiveWorkbenchWindow(), this.searchText);
if (curSearchText != null) {
searchText.setText(curSearchText);
searchText.setSelection(curSearchText.length());
}
//searchText.setBackground(searchNotFoundColor);
searchText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
searchText.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
switch (e.keyCode) {
case SWT.ESC:
cancelSearch(true);
break;
case SWT.CR:
case SWT.ARROW_UP:
case SWT.ARROW_DOWN:
if (childPageControl != null) {
childPageControl.setFocus();
searchControlsComposite.getParent().setRedraw(false);
try {
searchText = new Text(searchControlsComposite, SWT.BORDER);
UIUtils.addDefaultEditActionsSupport(UIUtils.getActiveWorkbenchWindow(), this.searchText);
if (curSearchText != null) {
searchText.setText(curSearchText);
searchText.setSelection(curSearchText.length());
}
//searchText.setBackground(searchNotFoundColor);
searchText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
searchText.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
switch (e.keyCode) {
case SWT.ESC:
cancelSearch(true);
break;
case SWT.CR:
case SWT.ARROW_UP:
case SWT.ARROW_DOWN:
if (childPageControl != null) {
childPageControl.setFocus();
}
e.doit = false;
//performSearch(SearchType.NEXT);
break;
}
}
});
searchText.addModifyListener(e -> {
curSearchText = searchText.getText();
if (curSearchJob == null) {
curSearchJob = new UIJob(UIMessages.controls_progress_page_job_search) {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
performSearch(SearchType.NEXT);
curSearchJob = null;
return Status.OK_STATUS;
}
e.doit = false;
//performSearch(SearchType.NEXT);
break;
};
curSearchJob.schedule(200);
}
}
});
searchText.addModifyListener(e -> {
curSearchText = searchText.getText();
if (curSearchJob == null) {
curSearchJob = new UIJob(UIMessages.controls_progress_page_job_search) {
});
//ToolBar searchTools = new ToolBar(searchControlsComposite, SWT.HORIZONTAL);
if (searchToolbarManager == null) {
searchToolbarManager = new ToolBarManager(SWT.FLAT | SWT.HORIZONTAL);
// Do not add prev/next buttons - they doesn't make sense now.
// Keep code just in case
/*
searchToolbarManager.add(ActionUtils.makeCommandContribution(
PlatformUI.getWorkbench(),
IWorkbenchActionDefinitionIds.FIND_NEXT,
null,
UIIcon.ARROW_DOWN));
searchToolbarManager.add(ActionUtils.makeCommandContribution(
PlatformUI.getWorkbench(),
IWorkbenchActionDefinitionIds.FIND_PREVIOUS,
null,
UIIcon.ARROW_UP));
*/
searchToolbarManager.add(new Action(UIMessages.controls_progress_page_action_close, UIUtils.getShardImageDescriptor(ISharedImages.IMG_ELCL_REMOVE)) {
@Override
public IStatus runInUIThread(IProgressMonitor monitor)
{
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
performSearch(SearchType.NEXT);
curSearchJob = null;
return Status.OK_STATUS;
public void run() {
cancelSearch(true);
}
};
curSearchJob.schedule(200);
});
}
});
searchToolbarManager.createControl(searchControlsComposite);
//ToolBar searchTools = new ToolBar(searchControlsComposite, SWT.HORIZONTAL);
if (searchToolbarManager == null) {
searchToolbarManager = new ToolBarManager(SWT.FLAT | SWT.HORIZONTAL);
// Do not add prev/next buttons - they doesn't make sense now.
// Keep code just in case
/*
searchToolbarManager.add(ActionUtils.makeCommandContribution(
PlatformUI.getWorkbench(),
IWorkbenchActionDefinitionIds.FIND_NEXT,
null,
UIIcon.ARROW_DOWN));
searchToolbarManager.add(ActionUtils.makeCommandContribution(
PlatformUI.getWorkbench(),
IWorkbenchActionDefinitionIds.FIND_PREVIOUS,
null,
UIIcon.ARROW_UP));
*/
searchToolbarManager.add(new Action(UIMessages.controls_progress_page_action_close, UIUtils.getShardImageDescriptor(ISharedImages.IMG_ELCL_REMOVE)) {
@Override
public void run()
{
cancelSearch(true);
}
});
searchControlsComposite.getParent().layout();
} finally {
searchControlsComposite.getParent().setRedraw(true);
}
searchToolbarManager.createControl(searchControlsComposite);
searchControlsComposite.getParent().layout();
}
public void disposeControl()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册