diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/model/sql/SQLUtils.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/model/sql/SQLUtils.java index aaf6cf72af4a9519e1ca994b429c59bb95b8e175..e11d36876ba5d7a2eb753b7409d462be80c2a5fd 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/model/sql/SQLUtils.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/model/sql/SQLUtils.java @@ -237,20 +237,21 @@ public final class SQLUtils { public static String trimQueryStatement(SQLSyntaxManager syntaxManager, String sql) { sql = sql.trim(); - String statementDelimiter = syntaxManager.getStatementDelimiter(); - if (sql.endsWith(statementDelimiter) && sql.length() > statementDelimiter.length()) { - if (Character.isAlphabetic(statementDelimiter.charAt(0))) { - // Delimiter is alphabetic (e.g. "GO") so it must be prefixed with whitespace - char lastChar = sql.charAt(sql.length() - statementDelimiter.length() - 1); - if (Character.isUnicodeIdentifierPart(lastChar)) { - return sql; + for (String statementDelimiter : syntaxManager.getStatementDelimiters()) { + if (sql.endsWith(statementDelimiter) && sql.length() > statementDelimiter.length()) { + if (Character.isAlphabetic(statementDelimiter.charAt(0))) { + // Delimiter is alphabetic (e.g. "GO") so it must be prefixed with whitespace + char lastChar = sql.charAt(sql.length() - statementDelimiter.length() - 1); + if (Character.isUnicodeIdentifierPart(lastChar)) { + return sql; + } + } + // Remove trailing delimiter only if it is not block end + String trimmed = sql.substring(0, sql.length() - statementDelimiter.length()); + String test = trimmed.toUpperCase().trim(); + if (!test.endsWith(SQLConstants.BLOCK_END)) { + sql = trimmed; } - } - // Remove trailing delimiter only if it is not block end - String trimmed = sql.substring(0, sql.length() - statementDelimiter.length()); - String test = trimmed.toUpperCase().trim(); - if (!test.endsWith(SQLConstants.BLOCK_END)) { - sql = trimmed; } } return sql; diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/SQLEditor.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/SQLEditor.java index 7db6c0989018d32d050ead02c62d8277fd9c0065..46c148ef56003d32c0796723b4b026fceb566eeb 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/SQLEditor.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/SQLEditor.java @@ -29,6 +29,8 @@ import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.text.*; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; @@ -97,8 +99,7 @@ import java.util.concurrent.atomic.AtomicInteger; * SQL Executor */ public class SQLEditor extends SQLEditorBase - implements IDataSourceContainerProviderEx, DBPEventListener, ISaveablePart2, IResultSetContainer, DBPDataSourceUser, DBPDataSourceHandler -{ + implements IDataSourceContainerProviderEx, DBPEventListener, ISaveablePart2, IResultSetContainer, DBPDataSourceUser, DBPDataSourceHandler, IPropertyChangeListener { private static final long SCRIPT_UI_UPDATE_PERIOD = 100; private static Image IMG_DATA_GRID = DBeaverActivator.getImageDescriptor("/icons/sql/page_data_grid.png").createImage(); //$NON-NLS-1$ @@ -189,6 +190,7 @@ public class SQLEditor extends SQLEditorBase } // Acquire ds container if (dataSourceContainer != null) { + dataSourceContainer.getPreferenceStore().removePropertyChangeListener(this); dataSourceContainer.release(this); dataSourceContainer = null; } @@ -196,6 +198,9 @@ public class SQLEditor extends SQLEditorBase closeAllJobs(); dataSourceContainer = container; + if (dataSourceContainer != null) { + dataSourceContainer.getPreferenceStore().addPropertyChangeListener(this); + } IPathEditorInput input = getEditorInput(); if (input == null) { return false; @@ -691,10 +696,7 @@ public class SQLEditor extends SQLEditorBase public void dispose() { // Acquire ds container - final DBSDataSourceContainer dsContainer = getDataSourceContainer(); - if (dsContainer != null) { - dsContainer.release(this); - } + setDataSourceContainer(null); closeAllJobs(); @@ -871,6 +873,13 @@ public class SQLEditor extends SQLEditorBase return queryProcessor; } + @Override + public void propertyChange(PropertyChangeEvent event) { + if (event.getProperty().equals(DBeaverPreferences.SCRIPT_STATEMENT_DELIMITER)) { + reloadSyntaxRules(); + } + } + public class QueryProcessor implements SQLResultsConsumer { private SQLQueryJob curJob; diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/SQLEditorBase.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/SQLEditorBase.java index 8d5f169568f63905411c42dc8c54245b09c9a4f1..4ed48bfc74fb3ff69aea55f6ce759f8d06d54c55 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/SQLEditorBase.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/SQLEditorBase.java @@ -70,6 +70,8 @@ import org.jkiss.dbeaver.ui.editors.sql.util.SQLSymbolInserter; import org.jkiss.dbeaver.ui.editors.text.BaseTextEditor; import org.jkiss.utils.CommonUtils; +import java.util.Collection; +import java.util.Collections; import java.util.ResourceBundle; /** @@ -577,15 +579,17 @@ public abstract class SQLEditorBase extends BaseTextEditor { String queryText = document.get(statementStart, tokenOffset - statementStart); queryText = queryText.trim(); - String delimiterText; + Collection delimiterTexts; if (isDelimiter) { - delimiterText = document.get(tokenOffset, tokenLength); + delimiterTexts = Collections.singleton(document.get(tokenOffset, tokenLength)); } else { - delimiterText = syntaxManager.getStatementDelimiter(); + delimiterTexts = syntaxManager.getStatementDelimiters(); } - if (queryText.endsWith(delimiterText)) { - queryText = queryText.substring(0, queryText.length() - delimiterText.length()); + for (String delim : delimiterTexts) { + if (queryText.endsWith(delim)) { + queryText = queryText.substring(0, queryText.length() - delim.length()); + } } // make script line return new SQLQuery( diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/format/tokenized/SQLTokenizedFormatter.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/format/tokenized/SQLTokenizedFormatter.java index 3c329d932cd42f01eeeaa270957d24e20086f991..6ccedd78f4e683fed15d212b77edba820474fae9 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/format/tokenized/SQLTokenizedFormatter.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/format/tokenized/SQLTokenizedFormatter.java @@ -19,13 +19,13 @@ package org.jkiss.dbeaver.ui.editors.sql.format.tokenized; -import org.jkiss.dbeaver.ui.editors.sql.SQLConstants; import org.jkiss.dbeaver.ui.editors.sql.format.SQLFormatter; import org.jkiss.dbeaver.ui.editors.sql.format.SQLFormatterConfiguration; import org.jkiss.dbeaver.utils.ContentUtils; import org.jkiss.utils.Pair; import java.util.ArrayList; +import java.util.Collection; import java.util.List; /** @@ -34,14 +34,13 @@ import java.util.List; public class SQLTokenizedFormatter implements SQLFormatter { private SQLFormatterConfiguration formatterCfg; private List functionBracket = new ArrayList(); - private List statementDelimiters = new ArrayList(2); + private Collection statementDelimiters = new ArrayList(2); @Override public String format(final String argSql, SQLFormatterConfiguration configuration) { formatterCfg = configuration; - statementDelimiters.add(SQLConstants.DEFAULT_STATEMENT_DELIMITER); - statementDelimiters.add(formatterCfg.getSyntaxManager().getStatementDelimiter().toUpperCase()); + statementDelimiters = formatterCfg.getSyntaxManager().getStatementDelimiters(); SQLTokensParser fParser = new SQLTokensParser(formatterCfg); functionBracket.clear(); diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/syntax/SQLSyntaxManager.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/syntax/SQLSyntaxManager.java index f92129962ee07030c8014c4b337debe1c42b856c..591ab9ba2b58a37a2396c0fc162c48bdd9fdd15a 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/syntax/SQLSyntaxManager.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/syntax/SQLSyntaxManager.java @@ -29,6 +29,7 @@ import org.eclipse.ui.themes.ITheme; import org.eclipse.ui.themes.IThemeManager; import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; +import org.jkiss.dbeaver.DBeaverPreferences; import org.jkiss.dbeaver.model.impl.sql.BasicSQLDialect; import org.jkiss.dbeaver.model.sql.SQLDataSource; import org.jkiss.dbeaver.model.sql.SQLDialect; @@ -59,7 +60,7 @@ public class SQLSyntaxManager extends RuleBasedScanner { @NotNull private String catalogSeparator; @NotNull - private String statementDelimiter = SQLConstants.DEFAULT_STATEMENT_DELIMITER; + private Set statementDelimiters = new LinkedHashSet();//SQLConstants.DEFAULT_STATEMENT_DELIMITER; @NotNull private TreeMap positions = new TreeMap(); @@ -101,9 +102,9 @@ public class SQLSyntaxManager extends RuleBasedScanner { } @NotNull - public String getStatementDelimiter() + public Set getStatementDelimiters() { - return statementDelimiter; + return statementDelimiters; } @Nullable @@ -142,13 +143,14 @@ public class SQLSyntaxManager extends RuleBasedScanner { { this.unassigned = dataSource == null; this.dataSource = dataSource; + this.statementDelimiters.clear(); if (this.dataSource == null) { sqlDialect = new BasicSQLDialect(); quoteSymbol = null; structSeparator = SQLConstants.STRUCT_SEPARATOR; catalogSeparator = String.valueOf(SQLConstants.STRUCT_SEPARATOR); escapeChar = '\\'; - statementDelimiter = SQLConstants.DEFAULT_STATEMENT_DELIMITER; + statementDelimiters.add(SQLConstants.DEFAULT_STATEMENT_DELIMITER); } else { sqlDialect = this.dataSource.getSQLDialect(); quoteSymbol = sqlDialect.getIdentifierQuoteString(); @@ -156,7 +158,13 @@ public class SQLSyntaxManager extends RuleBasedScanner { catalogSeparator = sqlDialect.getCatalogSeparator(); sqlDialect.getSearchStringEscape(); escapeChar = '\\'; - statementDelimiter = sqlDialect.getScriptDelimiter().toLowerCase(); + statementDelimiters.add(sqlDialect.getScriptDelimiter().toLowerCase()); + + String extraDelimiters = this.dataSource.getContainer().getPreferenceStore().getString(DBeaverPreferences.SCRIPT_STATEMENT_DELIMITER); + StringTokenizer st = new StringTokenizer(extraDelimiters, " \t,"); + while (st.hasMoreTokens()) { + statementDelimiters.add(st.nextToken()); + } } } @@ -223,27 +231,26 @@ public class SQLSyntaxManager extends RuleBasedScanner { // Add numeric rule rules.add(new NumberRule(numberToken)); - { - // Default delim rule - WordRule delimRule = new WordRule(new IWordDetector() { - @Override - public boolean isWordStart(char c) - { - return SQLConstants.DEFAULT_STATEMENT_DELIMITER.charAt(0) == c; - } + for (final String delimiter : statementDelimiters) { + WordRule delimRule; + if (Character.isLetterOrDigit(delimiter.charAt(0))) { + delimRule = new WordRule(new SQLWordDetector(), Token.UNDEFINED, true); + delimRule.addWord(delimiter, delimiterToken); + } else { + // Default delim rule + delimRule = new WordRule(new IWordDetector() { + @Override + public boolean isWordStart(char c) { + return delimiter.charAt(0) == c; + } - @Override - public boolean isWordPart(char c) - { - return SQLConstants.DEFAULT_STATEMENT_DELIMITER.indexOf(c) != -1; - } - }, Token.UNDEFINED, false); - delimRule.addWord(SQLConstants.DEFAULT_STATEMENT_DELIMITER, delimiterToken); - rules.add(delimRule); - } - if (!statementDelimiter.equals(SQLConstants.DEFAULT_STATEMENT_DELIMITER)) { - WordRule delimRule = new WordRule(new SQLWordDetector(), Token.UNDEFINED, true); - delimRule.addWord(statementDelimiter, delimiterToken); + @Override + public boolean isWordPart(char c) { + return delimiter.indexOf(c) != -1; + } + }, Token.UNDEFINED, false); + delimRule.addWord(delimiter, delimiterToken); + } rules.add(delimRule); } diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/syntax/SQLWordPartDetector.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/syntax/SQLWordPartDetector.java index 243d02072159dba881c5d1c2ce85c9ded7ed31dc..7a1d8d2242a44750dbaff3922391b4ac76a41b4e 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/syntax/SQLWordPartDetector.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/sql/syntax/SQLWordPartDetector.java @@ -21,7 +21,6 @@ package org.jkiss.dbeaver.ui.editors.sql.syntax; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; -import org.jkiss.dbeaver.model.DBPKeywordType; import org.jkiss.dbeaver.model.sql.SQLDialect; import java.util.ArrayList; @@ -83,9 +82,11 @@ public class SQLWordPartDetector extends SQLIdentifierDetector if (prevDelimiter == null) { prevDelimiter = prevPiece.toString(); } - if (prevPiece.indexOf(syntaxManager.getStatementDelimiter()) != -1) { - // Statement delimiter found - do not process to previous keyword - return; + for (String delim : syntaxManager.getStatementDelimiters()) { + if (prevPiece.indexOf(delim) != -1) { + // Statement delimiter found - do not process to previous keyword + return; + } } int prevStartOffset = prevOffset + 1; while (prevOffset >= topIndex) {