提交 3d2a4988 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Do not allocate substrings for keywords

上级 63b0d08b
...@@ -4338,9 +4338,12 @@ public class Parser { ...@@ -4338,9 +4338,12 @@ public class Parser {
} }
i++; i++;
} }
currentToken = StringUtils.cache(sqlCommand.substring( currentTokenType = ParserUtil.getSaveTokenType(sqlCommand, !identifiersToUpper, start, i, false);
start, i)); if (currentTokenType == IDENTIFIER) {
currentTokenType = getTokenType(currentToken); currentToken = StringUtils.cache(sqlCommand.substring(start, i));
} else {
currentToken = TOKENS[currentTokenType];
}
parseIndex = i; parseIndex = i;
return; return;
case CHAR_QUOTED: { case CHAR_QUOTED: {
...@@ -4896,18 +4899,6 @@ public class Parser { ...@@ -4896,18 +4899,6 @@ public class Parser {
throw getSyntaxError(); throw getSyntaxError();
} }
private int getTokenType(String s) {
int len = s.length();
if (len == 0) {
throw getSyntaxError();
}
if (!identifiersToUpper) {
// if not yet converted to uppercase, do it now
s = StringUtils.toUpperEnglish(s);
}
return ParserUtil.getSaveTokenType(s, false);
}
private boolean isKeyword(String s) { private boolean isKeyword(String s) {
if (!identifiersToUpper) { if (!identifiersToUpper) {
// if not yet converted to uppercase, do it now // if not yet converted to uppercase, do it now
......
...@@ -241,7 +241,7 @@ public class ParserUtil { ...@@ -241,7 +241,7 @@ public class ParserUtil {
if (s.length() == 0) { if (s.length() == 0) {
return false; return false;
} }
return getSaveTokenType(s, false) != IDENTIFIER; return getSaveTokenType(s, false, 0, s.length(), false) != IDENTIFIER;
} }
/** /**
...@@ -266,176 +266,186 @@ public class ParserUtil { ...@@ -266,176 +266,186 @@ public class ParserUtil {
return false; return false;
} }
} }
return getSaveTokenType(s, true) == IDENTIFIER; return getSaveTokenType(s, false, 0, s.length(), true) == IDENTIFIER;
} }
/** /**
* Get the token type. * Get the token type.
* *
* @param s the token * @param s the string with token
* @param ignoreCase true if case should be ignored, false if only upper case
* tokens are detected as keywords
* @param start start index of token
* @param end index of token
* @param additionalKeywords whether TOP, INTERSECTS, and "current data / * @param additionalKeywords whether TOP, INTERSECTS, and "current data /
* time" functions are keywords * time" functions are keywords
* @return the token type * @return the token type
*/ */
public static int getSaveTokenType(String s, boolean additionalKeywords) { public static int getSaveTokenType(String s, boolean ignoreCase, int start, int end, boolean additionalKeywords) {
/* /*
* JdbcDatabaseMetaData.getSQLKeywords() and tests should be updated when new * JdbcDatabaseMetaData.getSQLKeywords() and tests should be updated when new
* non-SQL:2003 keywords are introduced here. * non-SQL:2003 keywords are introduced here.
*/ */
switch (s.charAt(0)) { char c = s.charAt(start);
if (ignoreCase && c >= 'a') {
c -= 32;
}
switch (c) {
case 'A': case 'A':
if ("ALL".equals(s)) { if (eq("ALL", s, ignoreCase, start, end)) {
return ALL; return ALL;
} }
return IDENTIFIER; return IDENTIFIER;
case 'C': case 'C':
if ("CHECK".equals(s)) { if (eq("CHECK", s, ignoreCase, start, end)) {
return CHECK; return CHECK;
} else if ("CONSTRAINT".equals(s)) { } else if (eq("CONSTRAINT", s, ignoreCase, start, end)) {
return CONSTRAINT; return CONSTRAINT;
} else if ("CROSS".equals(s)) { } else if (eq("CROSS", s, ignoreCase, start, end)) {
return CROSS; return CROSS;
} }
if (additionalKeywords) { if (additionalKeywords) {
if ("CURRENT_DATE".equals(s) || "CURRENT_TIME".equals(s) || "CURRENT_TIMESTAMP".equals(s)) { if (eq("CURRENT_DATE", s, ignoreCase, start, end) || eq("CURRENT_TIME", s, ignoreCase, start, end)
|| eq("CURRENT_TIMESTAMP", s, ignoreCase, start, end)) {
return KEYWORD; return KEYWORD;
} }
} }
return IDENTIFIER; return IDENTIFIER;
case 'D': case 'D':
if ("DISTINCT".equals(s)) { if (eq("DISTINCT", s, ignoreCase, start, end)) {
return DISTINCT; return DISTINCT;
} }
return IDENTIFIER; return IDENTIFIER;
case 'E': case 'E':
if ("EXCEPT".equals(s)) { if (eq("EXCEPT", s, ignoreCase, start, end)) {
return EXCEPT; return EXCEPT;
} else if ("EXISTS".equals(s)) { } else if (eq("EXISTS", s, ignoreCase, start, end)) {
return EXISTS; return EXISTS;
} }
return IDENTIFIER; return IDENTIFIER;
case 'F': case 'F':
if ("FETCH".equals(s)) { if (eq("FETCH", s, ignoreCase, start, end)) {
return FETCH; return FETCH;
} else if ("FROM".equals(s)) { } else if (eq("FROM", s, ignoreCase, start, end)) {
return FROM; return FROM;
} else if ("FOR".equals(s)) { } else if (eq("FOR", s, ignoreCase, start, end)) {
return FOR; return FOR;
} else if ("FOREIGN".equals(s)) { } else if (eq("FOREIGN", s, ignoreCase, start, end)) {
return FOREIGN; return FOREIGN;
} else if ("FULL".equals(s)) { } else if (eq("FULL", s, ignoreCase, start, end)) {
return FULL; return FULL;
} else if ("FALSE".equals(s)) { } else if (eq("FALSE", s, ignoreCase, start, end)) {
return FALSE; return FALSE;
} }
return IDENTIFIER; return IDENTIFIER;
case 'G': case 'G':
if ("GROUP".equals(s)) { if (eq("GROUP", s, ignoreCase, start, end)) {
return GROUP; return GROUP;
} }
return IDENTIFIER; return IDENTIFIER;
case 'H': case 'H':
if ("HAVING".equals(s)) { if (eq("HAVING", s, ignoreCase, start, end)) {
return HAVING; return HAVING;
} }
return IDENTIFIER; return IDENTIFIER;
case 'I': case 'I':
if ("INNER".equals(s)) { if (eq("INNER", s, ignoreCase, start, end)) {
return INNER; return INNER;
} else if ("INTERSECT".equals(s)) { } else if (eq("INTERSECT", s, ignoreCase, start, end)) {
return INTERSECT; return INTERSECT;
} else if ("IS".equals(s)) { } else if (eq("IS", s, ignoreCase, start, end)) {
return IS; return IS;
} }
if (additionalKeywords) { if (additionalKeywords) {
if ("INTERSECTS".equals(s)) { if (eq("INTERSECTS", s, ignoreCase, start, end)) {
return KEYWORD; return KEYWORD;
} }
} }
return IDENTIFIER; return IDENTIFIER;
case 'J': case 'J':
if ("JOIN".equals(s)) { if (eq("JOIN", s, ignoreCase, start, end)) {
return JOIN; return JOIN;
} }
return IDENTIFIER; return IDENTIFIER;
case 'L': case 'L':
if ("LIMIT".equals(s)) { if (eq("LIMIT", s, ignoreCase, start, end)) {
return LIMIT; return LIMIT;
} else if ("LIKE".equals(s)) { } else if (eq("LIKE", s, ignoreCase, start, end)) {
return LIKE; return LIKE;
} }
if (additionalKeywords) { if (additionalKeywords) {
if ("LOCALTIME".equals(s) || "LOCALTIMESTAMP".equals(s)) { if (eq("LOCALTIME", s, ignoreCase, start, end) || eq("LOCALTIMESTAMP", s, ignoreCase, start, end)) {
return KEYWORD; return KEYWORD;
} }
} }
return IDENTIFIER; return IDENTIFIER;
case 'M': case 'M':
if ("MINUS".equals(s)) { if (eq("MINUS", s, ignoreCase, start, end)) {
return MINUS; return MINUS;
} }
return IDENTIFIER; return IDENTIFIER;
case 'N': case 'N':
if ("NOT".equals(s)) { if (eq("NOT", s, ignoreCase, start, end)) {
return NOT; return NOT;
} else if ("NATURAL".equals(s)) { } else if (eq("NATURAL", s, ignoreCase, start, end)) {
return NATURAL; return NATURAL;
} else if ("NULL".equals(s)) { } else if (eq("NULL", s, ignoreCase, start, end)) {
return NULL; return NULL;
} }
return IDENTIFIER; return IDENTIFIER;
case 'O': case 'O':
if ("OFFSET".equals(s)) { if (eq("OFFSET", s, ignoreCase, start, end)) {
return OFFSET; return OFFSET;
} else if ("ON".equals(s)) { } else if (eq("ON", s, ignoreCase, start, end)) {
return ON; return ON;
} else if ("ORDER".equals(s)) { } else if (eq("ORDER", s, ignoreCase, start, end)) {
return ORDER; return ORDER;
} }
return IDENTIFIER; return IDENTIFIER;
case 'P': case 'P':
if ("PRIMARY".equals(s)) { if (eq("PRIMARY", s, ignoreCase, start, end)) {
return PRIMARY; return PRIMARY;
} }
return IDENTIFIER; return IDENTIFIER;
case 'R': case 'R':
if ("ROWNUM".equals(s)) { if (eq("ROWNUM", s, ignoreCase, start, end)) {
return ROWNUM; return ROWNUM;
} }
return IDENTIFIER; return IDENTIFIER;
case 'S': case 'S':
if ("SELECT".equals(s)) { if (eq("SELECT", s, ignoreCase, start, end)) {
return SELECT; return SELECT;
} }
if (additionalKeywords) { if (additionalKeywords) {
if ("SYSDATE".equals(s) || "SYSTIME".equals(s) || "SYSTIMESTAMP".equals(s)) { if (eq("SYSDATE", s, ignoreCase, start, end) || eq("SYSTIME", s, ignoreCase, start, end)
|| eq("SYSTIMESTAMP", s, ignoreCase, start, end)) {
return KEYWORD; return KEYWORD;
} }
} }
return IDENTIFIER; return IDENTIFIER;
case 'T': case 'T':
if ("TRUE".equals(s)) { if (eq("TRUE", s, ignoreCase, start, end)) {
return TRUE; return TRUE;
} }
if (additionalKeywords) { if (additionalKeywords) {
if ("TODAY".equals(s) || "TOP".equals(s)) { if (eq("TODAY", s, ignoreCase, start, end) || eq("TOP", s, ignoreCase, start, end)) {
return KEYWORD; return KEYWORD;
} }
} }
return IDENTIFIER; return IDENTIFIER;
case 'U': case 'U':
if ("UNIQUE".equals(s)) { if (eq("UNIQUE", s, ignoreCase, start, end)) {
return UNIQUE; return UNIQUE;
} else if ("UNION".equals(s)) { } else if (eq("UNION", s, ignoreCase, start, end)) {
return UNION; return UNION;
} }
return IDENTIFIER; return IDENTIFIER;
case 'W': case 'W':
if ("WHERE".equals(s)) { if (eq("WHERE", s, ignoreCase, start, end)) {
return WHERE; return WHERE;
} else if ("WINDOW".equals(s)) { } else if (eq("WINDOW", s, ignoreCase, start, end)) {
return WINDOW; return WINDOW;
} else if ("WITH".equals(s)) { } else if (eq("WITH", s, ignoreCase, start, end)) {
return WITH; return WITH;
} }
return IDENTIFIER; return IDENTIFIER;
...@@ -444,4 +454,10 @@ public class ParserUtil { ...@@ -444,4 +454,10 @@ public class ParserUtil {
} }
} }
private static boolean eq(String expected, String s, boolean ignoreCase, int start, int end) {
int len = expected.length();
// First letter was already checked
return end - start == len && expected.regionMatches(ignoreCase, 1, s, start + 1, len - 1);
}
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论