From aec33fa2220559e2c9cb854782aef95fcc959e88 Mon Sep 17 00:00:00 2001 From: Serge Rider Date: Fri, 27 Dec 2019 13:20:16 +0300 Subject: [PATCH] #7460 PgSQL parser (code blocks recognition) fixes. Former-commit-id: de3192491c617af634a0399fec881370d6bc9060 --- .../dbeaver/ui/editors/sql/SQLEditorBase.java | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/plugins/org.jkiss.dbeaver.ui.editors.sql/src/org/jkiss/dbeaver/ui/editors/sql/SQLEditorBase.java b/plugins/org.jkiss.dbeaver.ui.editors.sql/src/org/jkiss/dbeaver/ui/editors/sql/SQLEditorBase.java index 9ff4de8e0c..91803bebb1 100644 --- a/plugins/org.jkiss.dbeaver.ui.editors.sql/src/org/jkiss/dbeaver/ui/editors/sql/SQLEditorBase.java +++ b/plugins/org.jkiss.dbeaver.ui.editors.sql/src/org/jkiss/dbeaver/ui/editors/sql/SQLEditorBase.java @@ -885,12 +885,19 @@ public abstract class SQLEditorBase extends BaseTextEditor implements DBPContext private static class ScriptBlockInfo { final ScriptBlockInfo parent; + final String togglePattern; boolean isHeader; // block started by DECLARE, FUNCTION, etc public ScriptBlockInfo(ScriptBlockInfo parent, boolean isHeader) { this.parent = parent; + this.togglePattern = null; this.isHeader = isHeader; } + + public ScriptBlockInfo(ScriptBlockInfo parent, String togglePattern) { + this.parent = parent; + this.togglePattern = togglePattern; + } } protected SQLScriptElement parseQuery(final IDocument document, final int startPos, final int endPos, final int currentPos, final boolean scriptMode, final boolean keepDelimiters) { @@ -907,7 +914,6 @@ public abstract class SQLEditorBase extends BaseTextEditor implements DBPContext boolean hasValuableTokens = false; ScriptBlockInfo curBlock = null; boolean hasBlocks = false; - String blockTogglePattern = null; int lastTokenLineFeeds = 0; int prevNotEmptyTokenType = SQLToken.T_UNKNOWN; String lastKeyword = null; @@ -975,12 +981,10 @@ public abstract class SQLEditorBase extends BaseTextEditor implements DBPContext } // Second toggle pattern must be the same as first one. // Toggles can be nested (PostgreSQL) and we need to count only outer - if (curBlock != null && curBlock.parent == null && togglePattern.equals(blockTogglePattern)) { + if (curBlock != null && curBlock.parent == null && togglePattern.equals(curBlock.togglePattern)) { curBlock = curBlock.parent; - blockTogglePattern = null; - } else if (curBlock == null && blockTogglePattern == null) { - curBlock = new ScriptBlockInfo(curBlock, false); - blockTogglePattern = togglePattern; + } else if (curBlock == null) { + curBlock = new ScriptBlockInfo(curBlock, togglePattern); } else { log.debug("Block toggle token inside another block. Can't process it"); } @@ -988,15 +992,26 @@ public abstract class SQLEditorBase extends BaseTextEditor implements DBPContext } else if (tokenType == SQLToken.T_BLOCK_BEGIN) { if (curBlock == null || !curBlock.isHeader) { curBlock = new ScriptBlockInfo(curBlock, false); - } else if (curBlock != null) { + } else { curBlock.isHeader = false; } hasBlocks = true; - } else if (curBlock != null && tokenType == SQLToken.T_BLOCK_END) { + } else if (tokenType == SQLToken.T_BLOCK_END) { // Sometimes query contains END clause without BEGIN. E.g. CASE, IF, etc. // This END doesn't mean block if (curBlock != null) { - curBlock = curBlock.parent; + if (!CommonUtils.isEmpty(curBlock.togglePattern)) { + // Block end inside of block toggle (#7460). + // Actually it is a result of some wrong SQL parse (e.g. we didn't recognize block begin correctly). + // However block toggle has higher priority. At the moment it is PostgreSQL specific. + try { + log.debug("Block end '" + document.get(tokenOffset, tokenLength) + "' inside of named block toggle '" + curBlock.togglePattern + "'. Ignore."); + } catch (Throwable e) { + log.debug(e); + } + } else { + curBlock = curBlock.parent; + } } } else if (isDelimiter && curBlock != null) { // Delimiter in some brackets - ignore it -- GitLab