📄 sqlparser.java
字号:
{ // If the first token we find after all the left parentheses // is SELECT or VALUES, it's a subquery. retval = true; break; } else { // If the first token we find after all the left parentheses // is neither SELECT nor VALUES, it's not a subquery. break; } } return retval; } /** * Determine whether the next sequence of tokens can be the beginning * of a rowValueConstructorList. A rowValueConstructorList is a comma- * separated list of expressions enclosed in parentheses. This presents * special problems, because an expression be nested within an * arbitrary number of parentheses. To determine whether a left * parenthesis introduces a rowValueConstructorList or an expression, * we need to find the closing parenthesis, and determine whether * the next token is a comma. * * For example, the following is a rowValueConstructorList: * * (((1)), 2) * * and the following is just an expression: * * (((1))) * * @return TRUE iff the next set of tokens is the beginning of a * subquery. */ private boolean rowValueConstructorListFollows() { int nesting; boolean retval = false; // A rowValueConstructorList starts with a left parenthesis if (getToken(1).kind == LEFT_PAREN) { // Keep track of the nesting of parens while looking ahead nesting = 1; for (int i = 2; true; i++) { int tokKind = getToken(i).kind; // Special case for NULL/DEFAULT because they are not allowed in // a parenthesized expression, so (null)/(default) must be seen // as a rowValueConstructorList with one element. if (i == 2 && (tokKind == NULL || tokKind == _DEFAULT)) { retval = true; break; } // There must be a COMMA at nesting level 1 (i.e. outside of // the first expression) for it to be a rowValueConstructorList if (nesting == 1 && tokKind == COMMA) { retval = true; break; } // If we run out of tokens before finding the last closing // parenthesis, it's not a rowValueConstructorList (it's // probably a syntax error, in fact) if (tokKind == EOF) { break; } // Increase the nesting for each (, and decrease it for each ) if (tokKind == LEFT_PAREN) { nesting++; } else if (tokKind == RIGHT_PAREN) { nesting--; } // Don't look any farther than the last closing parenthesis if (nesting == 0) { break; } } } return retval; } /** * Determine whether the next sequence of tokens can be the beginning * of a propertyList(). A properties list is the word "properties" * followed by a dot-separated list, followed by an =, * followed by a value. This means that the first token must be the word * "properties", and the third must be a period (from the dot-separated * list) or an =. * * @return TRUE iff the next set of tokens is the beginning of a * propertyList(). */ private boolean propertyListFollows() { int tokKind; return getToken(1).kind == PROPERTIES && ((tokKind = getToken(3).kind) == PERIOD || tokKind == EQUALS_OPERATOR ); } /** * Determine whether the next sequence of tokens can be the beginning * of a newInvocation(). A newInvocation() begins with the word "new" * followed by a dot-separated list of identifiers, followed * by a left parenthesis. * * @param startToken Token to look for new at * * @return TRUE iff the next set of tokens is the beginning of a * newInvocation(). */ private boolean newInvocationFollows(int startToken) { boolean retval = false; // newInvocation() starts with the word "new" if (getToken(startToken).kind == NEW) { // Look at every other token. Ignore the identifiers, because // they are hard to test for. for (int i = 2 + startToken; true; i += 2) { int tokKind = getToken(i).kind; // If we find a left parenthesis without any intervening // cruft, we have found a newInvocation() if (tokKind == LEFT_PAREN) { retval = true; break; } else if (tokKind != PERIOD) { // Anything other than a PERIOD is "cruft" break; } } } return retval; } /** * Determine whether the next sequence of tokens is a class name * * @param startToken Token to look for class name at * * @return TRUE iff the next set of tokens is the java class name */ boolean javaClassFollows() { boolean retval = false; // Look at every other token. Ignore the identifiers, because // they are hard to test for. for (int i = 2; true; i += 2) { int tokKind = getToken(i).kind; // If we find a '::' without any intervening // cruft, we have found a javaClass if (tokKind == DOUBLE_COLON) { retval = true; break; } else if (tokKind != PERIOD) { // Anything other than a PERIOD is "cruft" break; } } return retval; } /** * Determine whether the next sequence of tokens can be the beginning * of a FROM newInvocation(). A FROM newInvocation() begins with the words "from new" * followed by a dot-separated list of identifiers, followed * by a left parenthesis. * * @return TRUE iff the next set of tokens is the beginning of a * FROM newInvocation(). */ private boolean fromNewInvocationFollows() { boolean retval = false; // FROM newInvocation() starts with the words "from new" return (getToken(1).kind == FROM && newInvocationFollows(2)); } /** * Determine whether the next sequence of tokens can be the beginning * of a joinedTableExpression(). A joinedTableExpression() begins * with one of: * * JOIN * INNER JOIN * LEFT OUTER JOIN * RIGHT OUTER JOIN * * @return TRUE iff the next set of tokens is the beginning of a * joinedTableExpression(). */ private boolean joinedTableExpressionFollows() { boolean retval = false; int tokKind1 = getToken(1).kind; int tokKind2 = getToken(2).kind; if (tokKind1 == JOIN) { retval = true; } else if (tokKind1 == INNER && tokKind2 == JOIN) { retval = true; } else if ((tokKind1 == LEFT || tokKind1 == RIGHT) && tokKind2 == OUTER) { if (getToken(3).kind == JOIN) { retval = true; } } else if ((tokKind1 == LEFT || tokKind1 == RIGHT) && tokKind2 == JOIN) { retval = true; } return retval; } /** * Translate a token for the name of a built-in aggregate to a String * containing an aggregate name. */ private static String aggName(Token token) { String retval = null; switch (token.kind) { case MAX: retval = "MAX"; break; case AVG: retval = "AVG"; break; case MIN: retval = "MIN"; break; case SUM: retval = "SUM"; break; case COUNT: retval = "COUNT"; break; default: if (SanityManager.DEBUG) { SanityManager.THROWASSERT("Unexpected token type in aggName: " + token.kind); } break; } return retval; } /** * Translate a token for the name of a built-in aggregate to an * aggregate definition class. */ private static Class aggClass(Token token) { Class retval = null; switch (token.kind) { case MAX: case MIN: retval = MaxMinAggregateDefinition.class; break; case AVG: case SUM: retval = SumAvgAggregateDefinition.class; break; case COUNT: retval = CountAggregateDefinition.class; break; default: if (SanityManager.DEBUG) { SanityManager.THROWASSERT("Unexpected token type in aggClass: " + token.kind); } break; } return retval; } /** * Determine whether the next sequence of tokens can be the beginning * of another element in a PROPERTY list. These elements are of the * form: * * COMMA dot.separated.list = ... * * Look for the COMMA, the dots in the dot-separated list, and the = * * @return TRUE iff the next set of tokens is the beginning of a * another element in a PROPERTY list. */ private boolean anotherPropertyFollows() { boolean retval = false; // Element must start with COMMA if (getToken(1).kind == COMMA) { // Rest of element is dot-separated list with = at end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -