📄 sqlgrammar.jj
字号:
/** * Initializes the list of unnamed parameters, i.e., "?" parameters * * Usually, this routine just gets an empty list for the unnamed parameters. * * */ void initUnnamedParameterList() { parameterList = new Vector(); } /** * Makes a new unnamed ParameterNode and chains it onto parameterList. * * @return new unnamed parameter. * * @exception StandardException */ ParameterNode makeParameterNode( ) throws StandardException { ParameterNode parm; DataValueDescriptor sdv = null; if ((paramDefaults != null) && (parameterNumber < paramDefaults.length)) { sdv = (DataValueDescriptor) paramDefaults[parameterNumber]; } parm = (ParameterNode) nodeFactory.getNode( C_NodeTypes.PARAMETER_NODE, ReuseFactory.getInteger(parameterNumber), sdv, getContextManager()); parameterNumber++; parameterList.addElement(parm); return parm; } /** * Looks up an unnamed parameter given its parameter number. * * @param paramNumber Number of parameter in unnamed * parameter list. * * @return corresponding unnamed parameter. * */ ParameterNode lookupUnnamedParameter( int paramNumber ) { ParameterNode unnamedParameter; unnamedParameter = (ParameterNode) parameterList.elementAt( paramNumber ); return unnamedParameter; } /** * Translate a String containing a number into the appropriate type * of Numeric node. * * @exception StandardException Thrown on error */ ValueNode getNumericNode(String num) throws StandardException { ContextManager cm = getContextManager(); // first, see if it might be an integer try { return (ValueNode) nodeFactory.getNode( C_NodeTypes.INT_CONSTANT_NODE, new Integer(num), cm); } catch (NumberFormatException nfe) { // we catch because we want to continue on below } // next, see if it might be a long try { return (ValueNode) nodeFactory.getNode( C_NodeTypes.LONGINT_CONSTANT_NODE, new Long(num), cm); } catch (NumberFormatException nfe) { // we catch because we want to continue on below } return (ValueNode) nodeFactory.getNode( C_NodeTypes.DECIMAL_CONSTANT_NODE, num, cm); } /** * Determine whether the current token represents one of * the built-in aliases. * * @return TRUE iff the current token names a built-in alias */ private boolean isBuiltInAlias() { boolean retval = false; switch (token.kind) { case UCASE: case LCASE: case SQRT: case LOCATE: case ABS: case ABSVAL: case SUBSTR: case MOD: retval = true; break; default: retval = false; break; } return retval; } /** * Determine whether the next sequence of tokens represents one of * the common (built-in) datatypes. * * @return TRUE iff the next set of tokens names a common datatype */ boolean commonDatatypeName(boolean checkFollowingToken) { boolean retval = false; switch (getToken(1).kind) { case CHARACTER: case CHAR: case VARCHAR: case NVARCHAR: case NCHAR: case BIT: case NUMERIC: case DECIMAL: case DEC: case INTEGER: case INT: case SMALLINT: case LONGINT: case FLOAT: case REAL: case DATE: case TIME: case TIMESTAMP: case BOOLEAN: case DOUBLE: case BLOB: case CLOB: case NCLOB: case BINARY: // LARGE OBJECT case XML: retval = true; break; case LONG: if (checkFollowingToken == true) { switch (getToken(2).kind) { case VARCHAR: case NVARCHAR: case BINARY: case VARBINARY: case BIT: retval = true; break; } break; } else { retval = true; break; } case NATIONAL: if (checkFollowingToken == true) { switch (getToken(2).kind) { case CHAR: case CHARACTER: retval = true; break; } break; } else { retval = true; break; } } return retval; } /** * Get a DELETE node given the pieces. * * * @exception StandardException */ private QueryTreeNode getDeleteNode(FromTable fromTable, TableName tableName, ValueNode whereClause) throws StandardException { FromList fromList = (FromList) nodeFactory.getNode( C_NodeTypes.FROM_LIST, getContextManager()); QueryTreeNode retval; SelectNode resultSet; fromList.addFromTable(fromTable); resultSet = (SelectNode) nodeFactory.getNode( C_NodeTypes.SELECT_NODE, null, null, /* AGGREGATE list */ fromList, /* FROM list */ whereClause, /* WHERE clause */ null, /* GROUP BY list */ getContextManager()); retval = (QueryTreeNode) nodeFactory.getNode( C_NodeTypes.DELETE_NODE, tableName, resultSet, getContextManager()); setUpAndLinkParameters(); return retval; } /** * Get an UPDATE node given the pieces. * * * @exception StandardException */ private QueryTreeNode getUpdateNode(FromTable fromTable, TableName tableName, ResultColumnList setClause, ValueNode whereClause) throws StandardException { FromList fromList = (FromList) nodeFactory.getNode( C_NodeTypes.FROM_LIST, getContextManager()); QueryTreeNode retval; SelectNode resultSet; fromList.addFromTable(fromTable); resultSet = (SelectNode) nodeFactory.getNode( C_NodeTypes.SELECT_NODE, setClause, null, /* AGGREGATE list */ fromList, /* FROM list */ whereClause, /* WHERE clause */ null, /* GROUP BY list */ getContextManager()); retval = (QueryTreeNode) nodeFactory.getNode( C_NodeTypes.UPDATE_NODE, tableName, resultSet, getContextManager()); setUpAndLinkParameters(); return retval; } /** * Determine whether the next sequence of tokens can be the beginning * of a remainingPredicate() rule. * * @return TRUE iff the next set of tokens is the beginning of a * remainingPredicate() */ private boolean remainingPredicateFollows() { boolean retval = false; switch (getToken(1).kind) { case EQUALS_OPERATOR: case NOT_EQUALS_OPERATOR: case NOT_EQUALS_OPERATOR2: // != case LESS_THAN_OPERATOR: case GREATER_THAN_OPERATOR: case LESS_THAN_OR_EQUALS_OPERATOR: case GREATER_THAN_OR_EQUALS_OPERATOR: case IN: case LIKE: case BETWEEN: retval = true; break; case NOT: switch (getToken(2).kind) { case IN: case LIKE: case BETWEEN: retval = true; } break; } return retval; } /** * Determine whether the next token is a DROP * * @return TRUE iff the next token is DROP */ private boolean dropFollows() { if (getToken(1).kind == DROP) { return true; } else { return false; } } /** * Determine whether the next sequence of tokens can be the beginning * of a escapedValueFunction(). * * We check only for the punctuation here, because identifiers are * very hard to check for in semantic lookahead. * * @return TRUE iff the next set of tokens is the beginning of a * escapedValueFunction() */ private boolean escapedValueFunctionFollows() { if (getToken(1).kind != LEFT_BRACE) { return false; } return getToken(2).kind == FN; } /** * Determine whether the next sequence of tokens can be the beginning * of a columnInvocation() rule. columnInvocations start with * [ [ id . ] id . ] id . id ( * * We check only for the punctuation here, because identifiers are * very hard to check for in semantic lookahead. * * @return TRUE iff the next set of tokens is the beginning of a * columnInvocation() */ private boolean columnMethodInvocationFollows() { int tokKind; // First token must not be a built-in function name that can be // followed immediately by a PERIOD. There are only a few of // these - most built-in functions have a LEFT_PAREN following // the function name. // if we run out of token, it's probably a syntax error, // in fact tokKind = getToken(1).kind; if ( tokKind == EOF ) { return false; } // disambiguate from named parameter reference if ( getToken(1).image.charAt(0) == '?' ) { return false; } if (tokKind == CURRENT_DATE || tokKind == CURRENT_TIME || tokKind == CURRENT_TIMESTAMP || tokKind == CURRENT && (isDATETIME(getToken(2).kind)) ) { return false; } // Second token must be a PERIOD if (getToken(2).kind != PERIOD) { return false; } // We have established that we start with " id . " tokKind = getToken(4).kind; if (tokKind == LEFT_PAREN) { // id.id( return true; } // Not id.id(, so 4th token must be PERIOD if (tokKind != PERIOD) { return false; } tokKind = getToken(6).kind; if (tokKind == LEFT_PAREN) { // id.id.id( return true; } // Not id.id.id(, so 6th token must be PERIOD if (tokKind != PERIOD) { return false; } tokKind = getToken(8).kind; if (tokKind == LEFT_PAREN) { // id.id.id.id( return true; } return false; } /** * Determine whether the next sequence of tokens can be the beginning * of an aggregateNode()() rule. aggregateNodes() start with one * of the built-in aggregate names, or with an identifier followed * by "( DISTINCT". A non-distinct user-defined aggregate invocation * is treated as a staticMethodInvocationAlias() by the parser, * and the binding phase figures out what it really is by looking * at the data dictionary. * * We check only for the punctuation here, because identifiers are * very hard to check for in semantic lookahead. * * @return TRUE iff the next set of tokens is the beginning of a * aggregateNode() */ private boolean aggregateFollows() { boolean retval = false; switch (getToken(1).kind) { case MAX: case AVG: case MIN: case SUM: // This is a built-in aggregate retval = true; break; case COUNT: // COUNT is not a reserved word // This may eclipse use of COUNT as a function or a procedure that is probably what we want if (getToken(2).kind == LEFT_PAREN) retval = true; default: // Not a built-in aggregate - assume the first token is an // identifier, and see whether it is followed by " ( DISTINCT " if (getToken(2).kind == LEFT_PAREN && getToken(3).kind == DISTINCT) retval = true; break; } return retval; } /** * Determine whether the next sequence of tokens can be the beginning * of a miscBuiltins(). * * We check only for the punctuation here, because identifiers are * very hard to check for in semantic lookahead. * * @return TRUE iff the next set of tokens is the beginning of a * aggregateNode() */ private boolean miscBuiltinFollows() { boolean retval = false; int tokKind = getToken(1).kind; if (getToken(0).kind == CALL) retval = true; switch (tokKind) { case GET_CURRENT_CONNECTION: case CURRENT_DATE: case CURRENT_TIME: case CURRENT_TIMESTAMP:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -