use of org.jkiss.dbeaver.ui.editors.sql.syntax.tokens.SQLToken in project dbeaver by dbeaver.
the class SQLEditorBase method parseParameters.
protected List<SQLQueryParameter> parseParameters(IDocument document, int queryOffset, int queryLength) {
final SQLDialect sqlDialect = getSQLDialect();
boolean supportParamsInDDL = getActivePreferenceStore().getBoolean(ModelPreferences.SQL_PARAMETERS_IN_DDL_ENABLED);
boolean execQuery = false;
List<SQLQueryParameter> parameters = null;
ruleManager.setRange(document, queryOffset, queryLength);
boolean firstKeyword = true;
for (; ; ) {
IToken token = ruleManager.nextToken();
final int tokenOffset = ruleManager.getTokenOffset();
final int tokenLength = ruleManager.getTokenLength();
if (token.isEOF() || tokenOffset > queryOffset + queryLength) {
break;
}
// Handle only parameters which are not in SQL blocks
int tokenType = SQLToken.T_UNKNOWN;
if (token instanceof SQLToken) {
tokenType = ((SQLToken) token).getType();
}
if (token.isWhitespace() || tokenType == SQLToken.T_COMMENT) {
continue;
}
if (!supportParamsInDDL) {
if (firstKeyword) {
// Detect query type
try {
String tokenText = document.get(tokenOffset, tokenLength);
if (ArrayUtils.containsIgnoreCase(sqlDialect.getDDLKeywords(), tokenText)) {
// DDL doesn't support parameters
return null;
}
execQuery = ArrayUtils.containsIgnoreCase(sqlDialect.getExecuteKeywords(), tokenText);
} catch (BadLocationException e) {
log.warn(e);
}
firstKeyword = false;
}
}
if (tokenType == SQLToken.T_PARAMETER && tokenLength > 0) {
try {
String paramName = document.get(tokenOffset, tokenLength);
if (execQuery && paramName.equals("?")) {
// Skip ? parameters for stored procedures (they have special meaning? [DB2])
continue;
}
if (parameters == null) {
parameters = new ArrayList<>();
}
SQLQueryParameter parameter = new SQLQueryParameter(parameters.size(), paramName, tokenOffset - queryOffset, tokenLength);
SQLQueryParameter previous = null;
if (parameter.isNamed()) {
for (int i = parameters.size(); i > 0; i--) {
if (parameters.get(i - 1).getName().equals(paramName)) {
previous = parameters.get(i - 1);
break;
}
}
}
parameter.setPrevious(previous);
parameters.add(parameter);
} catch (BadLocationException e) {
log.warn("Can't extract query parameter", e);
}
}
}
if (syntaxManager.isVariablesEnabled()) {
try {
// Find variables in strings, comments, etc
// Use regex
String query = document.get(queryOffset, queryLength);
Matcher matcher = SQLVariableRule.VARIABLE_PATTERN.matcher(query);
int position = 0;
while (matcher.find(position)) {
{
int start = matcher.start();
int orderPos = 0;
SQLQueryParameter param = null;
if (parameters != null) {
for (SQLQueryParameter p : parameters) {
if (p.getTokenOffset() == start) {
param = p;
break;
} else if (p.getTokenOffset() < start) {
orderPos++;
}
}
}
if (param == null) {
param = new SQLQueryParameter(orderPos, matcher.group(0), start, matcher.end() - matcher.start());
if (parameters == null) {
parameters = new ArrayList<>();
}
parameters.add(param.getOrdinalPosition(), param);
}
}
position = matcher.end();
}
} catch (BadLocationException e) {
log.warn("Error parsing variables", e);
}
}
return parameters;
}
use of org.jkiss.dbeaver.ui.editors.sql.syntax.tokens.SQLToken in project dbeaver by dbeaver.
the class SQLEditorBase method parseQuery.
protected SQLScriptElement parseQuery(final IDocument document, final int startPos, final int endPos, final int currentPos, final boolean scriptMode, final boolean keepDelimiters) {
if (endPos - startPos <= 0) {
return null;
}
SQLDialect dialect = getSQLDialect();
// Parse range
boolean useBlankLines = !scriptMode && syntaxManager.isBlankLineDelimiter();
ruleManager.setRange(document, startPos, endPos - startPos);
int statementStart = startPos;
int bracketDepth = 0;
boolean hasBlocks = false;
boolean hasValuableTokens = false;
boolean hasBlockHeader = false;
String blockTogglePattern = null;
int lastTokenLineFeeds = 0;
int prevNotEmptyTokenType = SQLToken.T_UNKNOWN;
for (; ; ) {
IToken token = ruleManager.nextToken();
int tokenOffset = ruleManager.getTokenOffset();
int tokenLength = ruleManager.getTokenLength();
int tokenType = token instanceof SQLToken ? ((SQLToken) token).getType() : SQLToken.T_UNKNOWN;
if (tokenOffset < startPos) {
// This may happen with EOF tokens (bug in jface?)
return null;
}
boolean isDelimiter = tokenType == SQLToken.T_DELIMITER;
boolean isControl = false;
String delimiterText = null;
try {
if (isDelimiter) {
// Save delimiter text
try {
delimiterText = document.get(tokenOffset, tokenLength);
} catch (BadLocationException e) {
log.debug(e);
}
} else if (useBlankLines && token.isWhitespace() && tokenLength >= 1) {
// Check for blank line delimiter
if (lastTokenLineFeeds + countLineFeeds(document, tokenOffset, tokenLength) >= 2) {
isDelimiter = true;
}
}
lastTokenLineFeeds = 0;
if (tokenLength == 1) {
// Check for bracket block begin/end
try {
char aChar = document.getChar(tokenOffset);
if (aChar == '(' || aChar == '{' || aChar == '[') {
bracketDepth++;
} else if (aChar == ')' || aChar == '}' || aChar == ']') {
bracketDepth--;
}
} catch (BadLocationException e) {
log.warn(e);
}
}
if (tokenType == SQLToken.T_BLOCK_BEGIN && prevNotEmptyTokenType == SQLToken.T_BLOCK_END) {
// This is a tricky thing.
// In some dialects block end looks like END CASE, END LOOP. It is parsed as
// Block end followed by block begin (as CASE and LOOP are block begin tokens)
// So let's ignore block begin if previos token was block end and there were no delimtiers.
tokenType = SQLToken.T_UNKNOWN;
}
if (tokenType == SQLToken.T_BLOCK_HEADER) {
bracketDepth++;
hasBlocks = true;
hasBlockHeader = true;
} else if (tokenType == SQLToken.T_BLOCK_TOGGLE) {
String togglePattern;
try {
togglePattern = document.get(tokenOffset, tokenLength);
} catch (BadLocationException e) {
log.warn(e);
togglePattern = "";
}
// Toggles can be nested (PostgreSQL) and we need to count only outer
if (bracketDepth == 1 && togglePattern.equals(blockTogglePattern)) {
bracketDepth--;
blockTogglePattern = null;
} else if (bracketDepth == 0 && blockTogglePattern == null) {
bracketDepth++;
blockTogglePattern = togglePattern;
} else {
log.debug("Block toggle token inside another block. Can't process it");
}
hasBlocks = true;
} else if (tokenType == SQLToken.T_BLOCK_BEGIN) {
if (!hasBlockHeader) {
bracketDepth++;
}
hasBlocks = true;
hasBlockHeader = false;
} else if (bracketDepth > 0 && tokenType == SQLToken.T_BLOCK_END) {
// This END doesn't mean block
if (hasBlocks) {
bracketDepth--;
}
hasBlockHeader = false;
} else if (isDelimiter && bracketDepth > 0) {
// Delimiter in some brackets - ignore it
continue;
} else if (tokenType == SQLToken.T_SET_DELIMITER || tokenType == SQLToken.T_CONTROL) {
isDelimiter = true;
isControl = true;
} else if (tokenType == SQLToken.T_COMMENT) {
lastTokenLineFeeds = tokenLength < 2 ? 0 : countLineFeeds(document, tokenOffset + tokenLength - 2, 2);
}
boolean cursorInsideToken = currentPos >= tokenOffset && currentPos < tokenOffset + tokenLength;
if (isControl && (scriptMode || cursorInsideToken) && !hasValuableTokens) {
// Control query
try {
String controlText = document.get(tokenOffset, tokenLength);
String commandId = null;
if (token instanceof SQLControlToken) {
commandId = ((SQLControlToken) token).getCommandId();
}
return new SQLControlCommand(getDataSource(), syntaxManager, controlText.trim(), commandId, tokenOffset, tokenLength, tokenType == SQLToken.T_SET_DELIMITER);
} catch (BadLocationException e) {
// $NON-NLS-1$
log.warn("Can't extract control statement", e);
return null;
}
}
if (hasValuableTokens && (token.isEOF() || (isDelimiter && tokenOffset >= currentPos) || tokenOffset > endPos)) {
if (tokenOffset > endPos) {
tokenOffset = endPos;
}
if (tokenOffset >= document.getLength()) {
// Sometimes (e.g. when comment finishing script text)
// last token offset is beyond document range
tokenOffset = document.getLength();
}
assert (tokenOffset >= currentPos);
try {
// remove leading spaces
while (statementStart < tokenOffset && Character.isWhitespace(document.getChar(statementStart))) {
statementStart++;
}
/*
while (statementStart < tokenOffset && Character.isWhitespace(document.getChar(tokenOffset - 1))) {
tokenOffset--;
tokenLength++;
}
*/
if (tokenOffset == statementStart) {
// Empty statement
if (token.isEOF()) {
return null;
}
statementStart = tokenOffset + tokenLength;
continue;
}
String queryText = document.get(statementStart, tokenOffset - statementStart);
queryText = SQLUtils.fixLineFeeds(queryText);
if (isDelimiter && (keepDelimiters || (hasBlocks ? dialect.isDelimiterAfterBlock() : dialect.isDelimiterAfterQuery()))) {
if (delimiterText != null && delimiterText.equals(SQLConstants.DEFAULT_STATEMENT_DELIMITER)) {
// Add delimiter in the end of query. Do this only for semicolon delimiters
// Quite dirty workaround needed for SQL server
queryText += delimiterText;
}
}
int queryEndPos = tokenOffset;
if (tokenType == SQLToken.T_DELIMITER) {
queryEndPos += tokenLength;
}
// make script line
return new SQLQuery(getDataSource(), queryText, statementStart, queryEndPos - statementStart);
} catch (BadLocationException ex) {
// $NON-NLS-1$
log.warn("Can't extract query", ex);
return null;
}
}
if (isDelimiter) {
statementStart = tokenOffset + tokenLength;
}
if (token.isEOF()) {
return null;
}
if (!hasValuableTokens && !token.isWhitespace() && !isControl) {
if (tokenType == SQLToken.T_COMMENT) {
hasValuableTokens = dialect.supportsCommentQuery();
} else {
hasValuableTokens = true;
}
}
} finally {
if (!token.isWhitespace() && !token.isEOF()) {
prevNotEmptyTokenType = tokenType;
}
}
}
}
Aggregations