/* Copyright (c) 2001-2019, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


package org.hsqldb;

import org.hsqldb.HsqlNameManager.HsqlName;
import org.hsqldb.HsqlNameManager.SimpleName;
import org.hsqldb.error.Error;
import org.hsqldb.error.ErrorCode;
import org.hsqldb.lib.ArrayUtil;
import org.hsqldb.lib.HashMappedList;
import org.hsqldb.lib.HsqlArrayList;
import org.hsqldb.lib.HsqlList;
import org.hsqldb.lib.Iterator;
import org.hsqldb.lib.LongDeque;
import org.hsqldb.lib.OrderedHashSet;
import org.hsqldb.lib.OrderedIntKeyHashMap;
import org.hsqldb.map.BitMap;
import org.hsqldb.map.ValuePool;
import org.hsqldb.result.ResultConstants;
import org.hsqldb.result.ResultProperties;
import org.hsqldb.types.ArrayType;
import org.hsqldb.types.BinaryType;
import org.hsqldb.types.BlobType;
import org.hsqldb.types.CharacterType;
import org.hsqldb.types.Charset;
import org.hsqldb.types.ClobType;
import org.hsqldb.types.Collation;
import org.hsqldb.types.DTIType;
import org.hsqldb.types.IntervalType;
import org.hsqldb.types.NumberType;
import org.hsqldb.types.Type;
import org.hsqldb.types.Types;
import org.hsqldb.types.UserTypeModifier;

Parser for DQL statements
Author:Fred Toussi (fredt@users dot sourceforge.net)
Version:2.5.0
Since:1.9.0
/** * Parser for DQL statements * * @author Fred Toussi (fredt@users dot sourceforge.net) * @version 2.5.0 * @since 1.9.0 */
public class ParserDQL extends ParserBase { protected Database database; protected Session session; protected final CompileContext compileContext;
Constructs a new Parser object with the given context.
Params:
  • session – the connected context
  • scanner – the token source from which to parse commands
/** * Constructs a new Parser object with the given context. * * @param session the connected context * @param scanner the token source from which to parse commands */
ParserDQL(Session session, Scanner scanner, CompileContext baseContext) { super(scanner); this.session = session; this.database = session.getDatabase(); this.compileContext = new CompileContext(session, this, baseContext); }
Resets this parse context with the given SQL character sequence.
Params:
  • sql – a new SQL character sequence to replace the current one
/** * Resets this parse context with the given SQL character sequence. * * @param sql a new SQL character sequence to replace the current one */
void reset(Session session, String sql) { super.reset(session, sql); compileContext.reset(); lastError = null; } void checkIsSchemaObjectName() { if (database.sqlEnforceNames) { checkIsNonReservedIdentifier(); } else { checkIsNonCoreReservedIdentifier(); } if (database.sqlRegularNames) { checkIsIrregularCharInIdentifier(); } } Type readTypeDefinition(boolean allowCollation, boolean includeUserTypes) { int typeNumber = Integer.MIN_VALUE; boolean hasLength = false; boolean hasScale = false; boolean isCharacter = false; boolean isIgnoreCase = false; boolean readByteOrChar = false; boolean enforceSize = database.sqlEnforceSize; checkIsIdentifier(); if (token.namePrefix == null) { typeNumber = Type.getTypeNr(token.tokenString); } if (database.sqlSyntaxOra && !session.isProcessingScript()) { if (typeNumber == Types.SQL_DATE) { read(); return Type.SQL_TIMESTAMP_NO_FRACTION; } } if (typeNumber == Integer.MIN_VALUE) { if (includeUserTypes) { checkIsSchemaObjectName(); Type type = database.schemaManager.findDomainOrUDT(session, token.tokenString, token.namePrefix, token.namePrePrefix, token.namePrePrePrefix); if (type != null) { getRecordedToken().setExpression(type); compileContext.addSchemaObject(type); read(); return type; } } if (token.namePrefix != null) { throw Error.error(ErrorCode.X_42509, token.tokenString); } if (database.sqlSyntaxOra) { switch (token.tokenType) { case Tokens.BINARY_DOUBLE : case Tokens.BINARY_FLOAT : read(); return Type.SQL_DOUBLE; case Tokens.LONG : read(); if (token.tokenType == Tokens.RAW) { read(); return Type.getType(Types.SQL_VARBINARY, null, null, BlobType.defaultBlobSize, 0); } else { readIfThis(Tokens.VARCHAR); return Type.getType(Types.SQL_VARCHAR, null, database.collation, ClobType.defaultClobSize, 0); } case Tokens.NUMBER : read(); if (token.tokenType == Tokens.OPENBRACKET) { read(); int precision = readInteger(); int scale = 0; if (token.tokenType == Tokens.COMMA) { read(); scale = readInteger(); } readThis(Tokens.CLOSEBRACKET); return Type.getType(Types.SQL_DECIMAL, null, null, precision, scale); } else { return Type.SQL_DECIMAL_DEFAULT; } case Tokens.RAW : typeNumber = Types.SQL_VARBINARY; break; case Tokens.VARCHAR2 : readByteOrChar = true; enforceSize = false; typeNumber = Types.SQL_VARCHAR; break; case Tokens.NVARCHAR2 : typeNumber = Types.SQL_VARCHAR; break; case Tokens.NCHAR : typeNumber = Types.SQL_CHAR; break; default : } } if (database.sqlSyntaxMss) { if (Tokens.T_MONEY.equals(token.tokenString)) { return Type.getType(Types.SQL_DECIMAL, null, null, 18, 4); } else if (Tokens.T_UNIQUEIDENTIFIER.equals( token.tokenString)) { return Type.SQL_GUID; } else if (Tokens.T_DATETIME2.equals(token.tokenString)) { typeNumber = Types.SQL_TIMESTAMP; } else if (Tokens.T_IMAGE.equals(token.tokenString)) { typeNumber = Types.LONGVARBINARY; } else if (Tokens.T_NTEXT.equals(token.tokenString)) { typeNumber = Types.LONGVARCHAR; } switch (token.tokenType) { case Tokens.DATETIMEOFFSET : typeNumber = Types.SQL_TIMESTAMP_WITH_TIME_ZONE; break; case Tokens.TEXT : typeNumber = Types.LONGVARCHAR; break; } } if (database.sqlSyntaxPgs) { switch (token.tokenType) { case Tokens.TEXT : typeNumber = Types.LONGVARCHAR; readByteOrChar = true; break; case Tokens.CITEXT : typeNumber = Types.VARCHAR_IGNORECASE; break; } } if (database.sqlSyntaxMys) { switch (token.tokenType) { case Tokens.ENUM : return readMysEnum(); case Tokens.TINYTEXT : typeNumber = Types.VARCHAR; readByteOrChar = true; break; case Tokens.TEXT : typeNumber = Types.LONGVARCHAR; readByteOrChar = true; break; case Tokens.MEDIUMTEXT : case Tokens.LONGTEXT : typeNumber = Types.LONGVARCHAR; readByteOrChar = true; break; case Tokens.TINYBLOB : typeNumber = Types.VARBINARY; break; case Tokens.MEDIUMBLOB : case Tokens.LONGBLOB : typeNumber = Types.LONGVARBINARY; break; } } if (typeNumber == Integer.MIN_VALUE) { throw Error.error(ErrorCode.X_42509, token.tokenString); } } read(); switch (typeNumber) { case Types.SQL_CHAR : if (token.tokenType == Tokens.VARYING) { read(); typeNumber = Types.SQL_VARCHAR; } else if (token.tokenType == Tokens.LARGE) { read(); readThis(Tokens.OBJECT); typeNumber = Types.SQL_CLOB; } else { if (database.sqlSyntaxOra) { readByteOrChar = true; } } break; case Types.SQL_DOUBLE : if (token.tokenType == Tokens.PRECISION) { read(); } break; case Types.SQL_BINARY : if (token.tokenType == Tokens.VARYING) { read(); typeNumber = Types.SQL_VARBINARY; } else if (token.tokenType == Tokens.LARGE) { read(); readThis(Tokens.OBJECT); typeNumber = Types.SQL_BLOB; } break; case Types.SQL_BIT : if (token.tokenType == Tokens.VARYING) { read(); typeNumber = Types.SQL_BIT_VARYING; } break; case Types.SQL_INTERVAL : return readIntervalType(session, false); default : } long length = typeNumber == Types.SQL_TIMESTAMP ? DTIType.defaultTimestampFractionPrecision : 0; int scale = 0; if (Types.requiresPrecision(typeNumber) && token.tokenType != Tokens.OPENBRACKET && enforceSize && !session.isProcessingScript()) { throw Error.error(ErrorCode.X_42599, Type.getDefaultType(typeNumber).getNameString()); } boolean acceptsPrecision = Types.acceptsPrecision(typeNumber); if (database.sqlSyntaxMys) { switch (typeNumber) { case Types.TINYINT : case Types.SQL_INTEGER : case Types.SQL_SMALLINT : case Types.SQL_BIGINT : acceptsPrecision = true; break; } } if (database.sqlSyntaxMss) { switch (typeNumber) { case Types.SQL_TIMESTAMP_WITH_TIME_ZONE : acceptsPrecision = true; break; } } if (acceptsPrecision) { if (token.tokenType == Tokens.OPENBRACKET) { int multiplier = 1; read(); switch (token.tokenType) { case Tokens.X_VALUE : if (token.dataType.typeCode != Types.SQL_INTEGER && token.dataType.typeCode != Types.SQL_BIGINT) { throw unexpectedToken(); } break; case Tokens.X_LOB_SIZE : if (typeNumber == Types.SQL_BLOB || typeNumber == Types.SQL_CLOB || typeNumber == Types.SQL_VARBINARY || typeNumber == Types.SQL_VARCHAR) { switch (token.lobMultiplierType) { case Tokens.K : multiplier = 1024; break; case Tokens.M : multiplier = 1024 * 1024; break; case Tokens.G : multiplier = 1024 * 1024 * 1024; break; case Tokens.P : case Tokens.T : default : throw unexpectedToken(); } break; } else { throw unexpectedToken(token.getFullString()); } case Tokens.MAX : if (database.sqlSyntaxMss) { token.tokenValue = Long.valueOf(Integer.MAX_VALUE); break; } throw unexpectedToken(); default : throw unexpectedToken(); } hasLength = true; length = ((Number) token.tokenValue).longValue(); if (length < 0 || (length == 0 && !Types.acceptsZeroPrecision(typeNumber))) { throw Error.error(ErrorCode.X_42592); } length *= multiplier; read(); if (typeNumber == Types.SQL_CHAR || typeNumber == Types.SQL_VARCHAR || typeNumber == Types.SQL_CLOB) { if (token.tokenType == Tokens.CHARACTERS) { read(); } else if (token.tokenType == Tokens.OCTETS) { read(); } } if (Types.acceptsScaleCreateParam(typeNumber) && token.tokenType == Tokens.COMMA) { read(); scale = readInteger(); if (scale < 0) { if (typeNumber == Types.SQL_DECIMAL && database.sqlSyntaxOra) { // } else { throw Error.error(ErrorCode.X_42592); } } if (typeNumber == Types.SQL_DECIMAL && scale > length) { throw Error.error(ErrorCode.X_42592); } hasScale = true; } if (readByteOrChar) { if (!readIfThis(Tokens.CHAR)) { readIfThis(Tokens.BYTE); } } readThis(Tokens.CLOSEBRACKET); } else if (typeNumber == Types.SQL_BIT) { length = 1; } else if (typeNumber == Types.SQL_BLOB || typeNumber == Types.SQL_CLOB) { length = BlobType.defaultBlobSize; } else if (enforceSize) { // BIT is always BIT(1), regardless of sqlEnforceSize if (typeNumber == Types.SQL_CHAR || typeNumber == Types.SQL_BINARY) { length = 1; } } switch (typeNumber) { case Types.SQL_TIMESTAMP_WITH_TIME_ZONE : case Types.SQL_TIMESTAMP : case Types.SQL_TIME : if (length > DTIType.maxFractionPrecision) { throw Error.error(ErrorCode.X_42592); } scale = (int) length; length = 0; if (typeNumber == Types.SQL_TIMESTAMP_WITH_TIME_ZONE) { break; } if (token.tokenType == Tokens.WITH) { read(); readThis(Tokens.TIME); readThis(Tokens.ZONE); if (typeNumber == Types.SQL_TIMESTAMP) { typeNumber = Types.SQL_TIMESTAMP_WITH_TIME_ZONE; } else { typeNumber = Types.SQL_TIME_WITH_TIME_ZONE; } } else if (token.tokenType == Tokens.WITHOUT) { read(); readThis(Tokens.TIME); readThis(Tokens.ZONE); } } } switch (typeNumber) { case Types.LONGVARCHAR : { if (database.sqlLongvarIsLob) { typeNumber = Types.SQL_CLOB; length = ClobType.defaultClobSize; } else { typeNumber = Types.SQL_VARCHAR; if (!hasLength) { length = ClobType.defaultShortClobSize; } } break; } case Types.LONGVARBINARY : { if (database.sqlLongvarIsLob) { typeNumber = Types.SQL_BLOB; length = BlobType.defaultBlobSize; } else { typeNumber = Types.SQL_VARBINARY; if (!hasLength) { length = BlobType.defaultShortBlobSize; } } break; } case Types.SQL_CHAR : if (database.sqlSyntaxDb2) { if (readIfThis(Tokens.FOR)) { readThis(Tokens.BIT); readThis(Tokens.DATA); typeNumber = Types.SQL_BINARY; break; } } isCharacter = true; break; case Types.SQL_CLOB : isCharacter = true; break; case Types.VARCHAR_IGNORECASE : typeNumber = Types.SQL_VARCHAR; isIgnoreCase = true; // fall through case Types.SQL_VARCHAR : if (database.sqlSyntaxDb2) { if (readIfThis(Tokens.FOR)) { readThis(Tokens.BIT); readThis(Tokens.DATA); typeNumber = Types.SQL_VARBINARY; if (!hasLength) { length = 32 * 1024; } break; } } isCharacter = true; if (!hasLength) { length = 32 * 1024; } if (session.isIgnorecase()) { if (!session.isProcessingScript()) { isIgnoreCase = true; } } if (length > CharacterType.maxCharPrecision) { throw Error.error(ErrorCode.X_42592); } break; case Types.SQL_BINARY : break; case Types.SQL_VARBINARY : if (!hasLength) { length = 32 * 1024; } if (length > BinaryType.maxBinaryPrecision) { throw Error.error(ErrorCode.X_42592); } break; case Types.SQL_DECIMAL : case Types.SQL_NUMERIC : if (!hasLength && !hasScale && !enforceSize) { length = NumberType.defaultNumericPrecision; scale = NumberType.defaultNumericScale; } break; } Collation collation = database.collation; Charset charset = null; if (isCharacter && allowCollation) { if (token.tokenType == Tokens.CHARACTER) { read(); readThis(Tokens.SET); checkIsSchemaObjectName(); charset = (Charset) database.schemaManager.getCharacterSet(session, token.tokenString, token.namePrefix); read(); } if (token.tokenType == Tokens.COLLATE) { read(); checkIsSchemaObjectName(); collation = database.schemaManager.getCollation(session, token.tokenString, token.namePrefix); read(); } else if (isIgnoreCase) { collation = Collation.getUpperCaseCompareCollation(collation); } } Type typeObject = Type.getType(typeNumber, charset, collation, length, scale); if (token.tokenType == Tokens.ARRAY) { if (typeObject.isLobType()) { throw unexpectedToken(); } read(); int maxCardinality = ArrayType.defaultArrayCardinality; if (token.tokenType == Tokens.LEFTBRACKET) { read(); maxCardinality = readInteger(); if (maxCardinality < 0) { throw Error.error(ErrorCode.X_42592); } readThis(Tokens.RIGHTBRACKET); } typeObject = new ArrayType(typeObject, maxCardinality); } return typeObject; } Type readMysEnum() { read(); checkIsThis(Tokens.OPENBRACKET); HsqlName name = database.nameManager.newHsqlName("ENUM", false, SchemaObject.DOMAIN); Type t = Type.getType(Types.SQL_VARCHAR, null, null, 32, 0); UserTypeModifier m = new UserTypeModifier(name, SchemaObject.DOMAIN, t); t.userTypeModifier = m; return t; } void readSimpleColumnNames(OrderedHashSet columns, RangeVariable rangeVar, boolean withPrefix) { while (true) { ColumnSchema col = readSimpleColumnName(rangeVar, withPrefix); if (!columns.add(col.getName().name)) { throw Error.error(ErrorCode.X_42579, col.getName().name); } if (readIfThis(Tokens.COMMA)) { continue; } if (token.tokenType == Tokens.CLOSEBRACKET) { break; } throw unexpectedToken(); } } void readTargetSpecificationList(OrderedHashSet targets, RangeVariable[] rangeVars, LongDeque colIndexList) { while (true) { Expression target = XreadTargetSpecification(rangeVars, colIndexList); if (!targets.add(target)) { ColumnSchema col = target.getColumn(); throw Error.error(ErrorCode.X_42579, col.getName().name); } if (readIfThis(Tokens.COMMA)) { continue; } if (token.tokenType == Tokens.CLOSEBRACKET) { break; } if (token.tokenType == Tokens.FROM) { break; } throw unexpectedToken(); } }
Process a bracketed column list as used in the declaration of SQL CONSTRAINTS and return an array containing the indexes of the columns within the table.
Params:
  • table – table that contains the columns
  • ascOrDesc – boolean
Returns:array of column indexes
/** * Process a bracketed column list as used in the declaration of SQL * CONSTRAINTS and return an array containing the indexes of the columns * within the table. * * @param table table that contains the columns * @param ascOrDesc boolean * @return array of column indexes */
int[] readColumnList(Table table, boolean ascOrDesc) { OrderedHashSet set = readColumnNames(ascOrDesc); return table.getColumnIndexes(set); } void readSimpleColumnNames(OrderedHashSet columns, Table table, boolean withPrefix) { while (true) { ColumnSchema col = readSimpleColumnName(table, withPrefix); if (!columns.add(col.getName().name)) { throw Error.error(ErrorCode.X_42577, col.getName().name); } if (readIfThis(Tokens.COMMA)) { continue; } if (token.tokenType == Tokens.CLOSEBRACKET) { break; } throw unexpectedToken(); } } HsqlName[] readColumnNames(HsqlName tableName) { BitMap quotedFlags = new BitMap(0, true); OrderedHashSet set = readColumnNames(quotedFlags, false); HsqlName[] colList = new HsqlName[set.size()]; for (int i = 0; i < colList.length; i++) { String name = (String) set.get(i); boolean quoted = quotedFlags.isSet(i); colList[i] = database.nameManager.newHsqlName(tableName.schema, name, quoted, SchemaObject.COLUMN, tableName); } return colList; } OrderedHashSet readColumnNames(boolean readAscDesc) { return readColumnNames(null, readAscDesc); } OrderedHashSet readColumnNames(BitMap quotedFlags, boolean readAscDesc) { readThis(Tokens.OPENBRACKET); OrderedHashSet set = new OrderedHashSet(); readColumnNameList(set, quotedFlags, readAscDesc); readThis(Tokens.CLOSEBRACKET); return set; } void readColumnNameList(OrderedHashSet set, BitMap quotedFlags, boolean readAscDesc) { int i = 0; while (true) { if (session.isProcessingScript()) { // for old scripts if (!isSimpleName()) { token.isDelimitedIdentifier = true; } } else { checkIsSimpleName(); } if (!set.add(token.tokenString)) { throw Error.error(ErrorCode.X_42577, token.tokenString); } if (quotedFlags != null) { quotedFlags.setValue(i, isDelimitedIdentifier()); } read(); i++; if (readAscDesc) { if (token.tokenType == Tokens.ASC || token.tokenType == Tokens.DESC) { read(); } } if (readIfThis(Tokens.COMMA)) { continue; } break; } } SimpleName[] readColumnNameList(OrderedHashSet set) { BitMap columnNameQuoted = new BitMap(0, true); readThis(Tokens.OPENBRACKET); readColumnNameList(set, columnNameQuoted, false); readThis(Tokens.CLOSEBRACKET); SimpleName[] columnNameList = new SimpleName[set.size()]; for (int i = 0; i < set.size(); i++) { SimpleName name = HsqlNameManager.getSimpleName((String) set.get(i), columnNameQuoted.isSet(i)); columnNameList[i] = name; } return columnNameList; } int XreadUnionType() { int unionType = QueryExpression.NOUNION; switch (token.tokenType) { case Tokens.UNION : read(); unionType = QueryExpression.UNION; if (token.tokenType == Tokens.ALL) { unionType = QueryExpression.UNION_ALL; read(); } else if (token.tokenType == Tokens.DISTINCT) { read(); } break; case Tokens.INTERSECT : read(); unionType = QueryExpression.INTERSECT; if (token.tokenType == Tokens.ALL) { unionType = QueryExpression.INTERSECT_ALL; read(); } else if (token.tokenType == Tokens.DISTINCT) { read(); } break; case Tokens.EXCEPT : case Tokens.MINUS_EXCEPT : read(); unionType = QueryExpression.EXCEPT; if (token.tokenType == Tokens.ALL) { unionType = QueryExpression.EXCEPT_ALL; read(); } else if (token.tokenType == Tokens.DISTINCT) { read(); } break; default : break; } return unionType; } void XreadUnionCorrespondingClause(QueryExpression queryExpression) { if (token.tokenType == Tokens.CORRESPONDING) { read(); queryExpression.setUnionCorresoponding(); if (token.tokenType == Tokens.BY) { read(); OrderedHashSet names = readColumnNames(false); queryExpression.setUnionCorrespondingColumns(names); } } } QueryExpression XreadQueryExpression() { if (token.tokenType == Tokens.WITH) { read(); boolean recursive = readIfThis(Tokens.RECURSIVE); compileContext.unregisterSubqueries(); while (true) { checkIsSimpleName(); HsqlName[] nameList = null; HsqlName queryName = database.nameManager.newHsqlName(token.tokenString, isDelimitedIdentifier(), SchemaObject.SUBQUERY); queryName.schema = SqlInvariants.SYSTEM_SCHEMA_HSQLNAME; read(); compileContext.registerSubquery(queryName.name); if (token.tokenType == Tokens.OPENBRACKET) { nameList = readColumnNames(queryName); } else if (recursive) { throw unexpectedTokenRequire(Tokens.T_OPENBRACKET); } readThis(Tokens.AS); readThis(Tokens.OPENBRACKET); TableDerived td; td = XreadTableNamedSubqueryBody(queryName, nameList, recursive ? OpTypes.RECURSIVE_SUBQUERY : OpTypes.TABLE_SUBQUERY); readThis(Tokens.CLOSEBRACKET); if (token.tokenType == Tokens.CYCLE) { throw unsupportedFeature(); } if (recursive && token.tokenType == Tokens.CYCLE) { Table table = td; int[] cycleColumnList = readColumnList(table, false); HsqlName name; readThis(Tokens.SET); checkIsSimpleName(); name = database.nameManager.newColumnHsqlName( table.getName(), token.tokenString, token.isDelimitedIdentifier); ColumnSchema cycleMarkColumn = new ColumnSchema(name, null, true, false, null); if (table.getColumnIndex(name.name) != -1) { throw Error.error(ErrorCode.X_42578, token.tokenString); } read(); readThis(Tokens.TO); String cycleMarkValue = readQuotedString(); if (cycleMarkValue.length() != 1) { throw unexpectedToken(cycleMarkValue); } readThis(Tokens.DEFAULT); String noncycleMarkValue = readQuotedString(); if (noncycleMarkValue.length() != 1) { throw unexpectedToken(noncycleMarkValue); } if (cycleMarkValue.equals(noncycleMarkValue)) { throw unexpectedToken(cycleMarkValue); } readThis(Tokens.USING); checkIsSimpleName(); checkIsSimpleName(); name = database.nameManager.newColumnHsqlName( table.getName(), token.tokenString, token.isDelimitedIdentifier); if (table.getColumnIndex(name.name) != -1) { throw Error.error(ErrorCode.X_42578, token.tokenString); } read(); ColumnSchema pathColumn = new ColumnSchema(name, null, true, false, null); } compileContext.registerSubquery(queryName.name, td); if (token.tokenType == Tokens.COMMA) { read(); continue; } break; } } QueryExpression queryExpression = XreadQueryExpressionBody(); SortAndSlice sortAndSlice = XreadOrderByExpression(); if (queryExpression.sortAndSlice == SortAndSlice.noSort) { queryExpression.addSortAndSlice(sortAndSlice); } else { if (queryExpression.sortAndSlice.hasLimit()) { if (sortAndSlice.hasLimit()) { throw Error.error(ErrorCode.X_42549); } for (int i = 0; i < sortAndSlice.exprList.size(); i++) { Expression e = (Expression) sortAndSlice.exprList.get(i); queryExpression.sortAndSlice.addOrderExpression(e); } } else { if (sortAndSlice != SortAndSlice.noSort) { queryExpression.addSortAndSlice(sortAndSlice); } } } compileContext.unregisterSubqueries(); return queryExpression; } QueryExpression XreadQueryExpressionBody() { QueryExpression queryExpression = XreadQueryTerm(); while (true) { switch (token.tokenType) { case Tokens.UNION : case Tokens.EXCEPT : case Tokens.MINUS_EXCEPT : { queryExpression = XreadSetOperation(queryExpression); break; } default : { return queryExpression; } } } } QueryExpression XreadQueryTerm() { QueryExpression queryExpression = XreadQueryPrimary(); while (true) { if (token.tokenType == Tokens.INTERSECT) { queryExpression = XreadSetOperation(queryExpression); } else { return queryExpression; } } } private QueryExpression XreadSetOperation( QueryExpression queryExpression) { queryExpression = new QueryExpression(compileContext, queryExpression); int unionType = XreadUnionType(); XreadUnionCorrespondingClause(queryExpression); QueryExpression rightQueryExpression = XreadQueryTerm(); queryExpression.addUnion(rightQueryExpression, unionType); return queryExpression; } QueryExpression XreadQueryPrimary() { switch (token.tokenType) { case Tokens.TABLE : case Tokens.VALUES : case Tokens.SELECT : { QuerySpecification select = XreadSimpleTable(); return select; } case Tokens.OPENBRACKET : { read(); QueryExpression queryExpression = XreadQueryExpressionBody(); SortAndSlice sortAndSlice = XreadOrderByExpression(); readThis(Tokens.CLOSEBRACKET); if (queryExpression.sortAndSlice == SortAndSlice.noSort) { queryExpression.addSortAndSlice(sortAndSlice); } else { if (queryExpression.sortAndSlice.hasLimit()) { if (sortAndSlice.hasLimit()) { throw Error.error(ErrorCode.X_42549); } for (int i = 0; i < sortAndSlice.exprList.size(); i++) { Expression e = (Expression) sortAndSlice.exprList.get(i); queryExpression.sortAndSlice.addOrderExpression(e); } } else { if (sortAndSlice != SortAndSlice.noSort) { queryExpression.addSortAndSlice(sortAndSlice); } } } return queryExpression; } default : { throw unexpectedToken(); } } } QuerySpecification XreadSimpleTable() { QuerySpecification select; switch (token.tokenType) { case Tokens.TABLE : { read(); Table table = readNamedSubqueryOrNull(); if (table == null) { table = readTableName(true); } if (table.isView()) { table = ((View) table).newDerivedTable(session, compileContext); } select = new QuerySpecification(session, table, compileContext, false); break; } case Tokens.VALUES : { read(); TableDerived td = XreadRowValueExpressionList(); select = new QuerySpecification(session, td, compileContext, true); break; } case Tokens.SELECT : { select = XreadQuerySpecification(); break; } default : { throw unexpectedToken(); } } return select; } QuerySpecification XreadQuerySpecification() { QuerySpecification select = XreadSelect(); if (!select.isValueList && select.getCurrentRangeVariableCount() == 0) { XreadTableExpression(select); } return select; } void XreadTableExpression(QuerySpecification select) { XreadFromClause(select); readWhereGroupHaving(select); } QuerySpecification XreadSelect() { QuerySpecification select = new QuerySpecification(compileContext); readThis(Tokens.SELECT); if (token.tokenType == Tokens.TOP || token.tokenType == Tokens.LIMIT) { SortAndSlice sortAndSlice = XreadTopOrLimit(); if (sortAndSlice != null) { select.addSortAndSlice(sortAndSlice); } } if (token.tokenType == Tokens.DISTINCT) { select.setDistinctSelect(); read(); } else if (token.tokenType == Tokens.ALL) { read(); } while (true) { Expression e = XreadValueExpression(); if (token.tokenType == Tokens.AS) { if (e.getType() == OpTypes.MULTICOLUMN) { throw unexpectedToken(); } read(); checkIsNonCoreReservedIdentifier(); } if (isNonCoreReservedIdentifier()) { if (e.getType() == OpTypes.MULTICOLUMN) { throw unexpectedToken(); } e.setAlias(HsqlNameManager.getSimpleName(token.tokenString, isDelimitedIdentifier())); read(); } select.addSelectColumnExpression(e); if (token.tokenType == Tokens.FROM) { break; } if (token.tokenType == Tokens.INTO) { break; } if (readIfThis(Tokens.COMMA)) { continue; } if (token.tokenType == Tokens.CLOSEBRACKET || token.tokenType == Tokens.X_ENDPARSE || token.tokenType == Tokens.SEMICOLON) { if (database.sqlSyntaxMss || database.sqlSyntaxMys || database.sqlSyntaxPgs) { RangeVariable range = new RangeVariable(database.schemaManager.dualTable, null, null, null, compileContext); select.addRangeVariable(session, range); return select; } } throw unexpectedToken(); } return select; } void XreadFromClause(QuerySpecification select) { readThis(Tokens.FROM); while (true) { XreadTableReference(select); if (readIfThis(Tokens.COMMA)) { // set last range as boundary continue; } break; } } void XreadTableReference(QuerySpecification select) { boolean natural = false; RangeVariable leftRange = readTableOrSubquery(); select.addRangeVariable(session, leftRange); while (true) { int type; boolean left = false; boolean right = false; boolean end = false; type = token.tokenType; switch (token.tokenType) { case Tokens.NATURAL : if (natural) { throw unexpectedToken(); } read(); natural = true; continue; case Tokens.INNER : read(); readThis(Tokens.JOIN); break; case Tokens.CROSS : if (natural) { throw unexpectedToken(); } read(); readThis(Tokens.JOIN); break; case Tokens.UNION : if (natural) { throw unexpectedToken(); } int position = getPosition(); read(); if (token.tokenType == Tokens.JOIN) { read(); left = true; right = true; break; } else { rewind(position); end = true; break; } case Tokens.LEFT : read(); readIfThis(Tokens.OUTER); readThis(Tokens.JOIN); left = true; break; case Tokens.RIGHT : read(); readIfThis(Tokens.OUTER); readThis(Tokens.JOIN); right = true; break; case Tokens.FULL : read(); readIfThis(Tokens.OUTER); readThis(Tokens.JOIN); left = true; right = true; break; case Tokens.JOIN : read(); type = Tokens.INNER; break; case Tokens.COMMA : default : if (natural) { throw unexpectedToken(); } end = true; break; } if (end) { break; } RangeVariable rightRange = readTableOrSubquery(); Expression condition = null; rightRange.setJoinType(left, right); switch (type) { case Tokens.CROSS : select.addRangeVariable(session, rightRange); break; case Tokens.UNION : condition = Expression.EXPR_FALSE; rightRange.addJoinCondition(condition); select.addRangeVariable(session, rightRange); break; case Tokens.LEFT : case Tokens.RIGHT : case Tokens.INNER : case Tokens.FULL : { boolean using = token.tokenType == Tokens.USING; if (natural || using) { leftRange.resolveRangeTable( session, RangeGroup.emptyGroup, compileContext.getOuterRanges()); rightRange.resolveRangeTable( session, RangeGroup.emptyGroup, compileContext.getOuterRanges()); } if (natural) { OrderedHashSet columns = rightRange.getUniqueColumnNameSet(); condition = select.getEquiJoinExpressions(columns, rightRange, false); rightRange.addJoinCondition(condition); select.addRangeVariable(session, rightRange); } else if (using) { read(); OrderedHashSet columns = new OrderedHashSet(); readThis(Tokens.OPENBRACKET); readSimpleColumnNames(columns, rightRange, false); readThis(Tokens.CLOSEBRACKET); condition = select.getEquiJoinExpressions(columns, rightRange, true); rightRange.addJoinCondition(condition); select.addRangeVariable(session, rightRange); } else if (token.tokenType == Tokens.ON) { read(); condition = XreadBooleanValueExpression(); rightRange.addJoinCondition(condition); select.addRangeVariable(session, rightRange); } else { throw unexpectedToken(); } break; } } natural = false; } } Expression getRowExpression(OrderedHashSet columnNames) { Expression[] elements = new Expression[columnNames.size()]; for (int i = 0; i < elements.length; i++) { String name = (String) columnNames.get(i); elements[i] = new ExpressionColumn(null, null, name); } return new Expression(OpTypes.ROW, elements); } void readWhereGroupHaving(QuerySpecification select) { // where if (token.tokenType == Tokens.WHERE) { read(); Expression e = XreadBooleanValueExpression(); select.addQueryCondition(e); } // group by if (token.tokenType == Tokens.GROUP) { read(); readThis(Tokens.BY); while (true) { Expression e = XreadValueExpression(); select.addGroupByColumnExpression(e); if (token.tokenType == Tokens.COMMA) { read(); continue; } break; } } // having if (token.tokenType == Tokens.HAVING) { read(); Expression e = XreadBooleanValueExpression(); select.addHavingExpression(e); } } SortAndSlice XreadOrderByExpression() { SortAndSlice sortAndSlice = null; if (token.tokenType == Tokens.ORDER) { read(); readThis(Tokens.BY); sortAndSlice = XreadOrderBy(); } if (token.tokenType == Tokens.LIMIT || token.tokenType == Tokens.FETCH || token.tokenType == Tokens.OFFSET) { if (sortAndSlice == null) { sortAndSlice = new SortAndSlice(); } XreadLimit(sortAndSlice); } return sortAndSlice == null ? SortAndSlice.noSort : sortAndSlice; } private SortAndSlice XreadTopOrLimit() { Expression e1 = null; Expression e2 = null; if (token.tokenType == Tokens.LIMIT) { int position = getPosition(); read(); e1 = XreadSimpleValueSpecificationOrNull(); if (e1 == null) { rewind(position); return null; } // optional comma readIfThis(Tokens.COMMA); e2 = XreadSimpleValueSpecificationOrNull(); if (e2 == null) { throw Error.error(ErrorCode.X_42563, ErrorCode.M_INVALID_LIMIT); } } else if (token.tokenType == Tokens.TOP) { int position = getPosition(); read(); e2 = XreadSimpleValueSpecificationOrNull(); if (e2 == null) { rewind(position); return null; } e1 = new ExpressionValue(ValuePool.INTEGER_0, Type.SQL_INTEGER); } else { throw unexpectedToken(); } boolean valid = true; if (e1.isUnresolvedParam()) { e1.setDataType(session, Type.SQL_INTEGER); } else if (e1.opType == OpTypes.VALUE) { valid = (e1.getDataType().typeCode == Types.SQL_INTEGER && ((Integer) e1.getValue(null)).intValue() >= 0); } else { throw Error.error(ErrorCode.X_42563, ErrorCode.M_INVALID_LIMIT); } if (e2.isUnresolvedParam()) { e2.setDataType(session, Type.SQL_INTEGER); } else if (e2.opType == OpTypes.VALUE) { valid &= (e2.getDataType().typeCode == Types.SQL_INTEGER && ((Integer) e2.getValue(null)).intValue() >= 0); } else { throw Error.error(ErrorCode.X_42563, ErrorCode.M_INVALID_LIMIT); } if (valid) { SortAndSlice sortAndSlice = new SortAndSlice(); sortAndSlice.addLimitCondition(new ExpressionOp(OpTypes.LIMIT, e1, e2)); return sortAndSlice; } throw Error.error(ErrorCode.X_42563, ErrorCode.M_INVALID_LIMIT); } private void XreadLimit(SortAndSlice sortAndSlice) { Expression e1 = null; Expression e2 = null; if (token.tokenType == Tokens.OFFSET) { read(); e1 = XreadSimpleValueSpecificationOrNull(); if (e1 == null) { throw Error.error(ErrorCode.X_42563, ErrorCode.M_INVALID_LIMIT); } if (token.tokenType == Tokens.ROW || token.tokenType == Tokens.ROWS) { read(); } } if (token.tokenType == Tokens.LIMIT) { read(); e2 = XreadSimpleValueSpecificationOrNull(); if (e2 == null) { throw Error.error(ErrorCode.X_42563, ErrorCode.M_INVALID_LIMIT); } if (e1 == null) { if (token.tokenType == Tokens.COMMA) { read(); e1 = e2; e2 = XreadSimpleValueSpecificationOrNull(); } else if (token.tokenType == Tokens.OFFSET) { read(); e1 = XreadSimpleValueSpecificationOrNull(); } } if (database.sqlSyntaxPgs || database.sqlSyntaxMys) { sortAndSlice.setZeroLimit(); } } else if (token.tokenType == Tokens.FETCH) { read(); if (token.tokenType == Tokens.FIRST || token.tokenType == Tokens.NEXT) { read(); } e2 = XreadSimpleValueSpecificationOrNull(); if (e2 == null) { e2 = new ExpressionValue(ValuePool.INTEGER_1, Type.SQL_INTEGER); } if (token.tokenType == Tokens.ROW || token.tokenType == Tokens.ROWS) { read(); } readThis(Tokens.ONLY); sortAndSlice.setStrictLimit(); } if (sortAndSlice.hasOrder() && token.tokenType == Tokens.USING) { read(); readThis(Tokens.INDEX); sortAndSlice.setUsingIndex(); } if (e1 == null) { e1 = new ExpressionValue(ValuePool.INTEGER_0, Type.SQL_INTEGER); } boolean valid = true; if (e1.isUnresolvedParam()) { e1.setDataType(session, Type.SQL_INTEGER); } if (e2 != null) { if (e2.isUnresolvedParam()) { e2.setDataType(session, Type.SQL_INTEGER); } } if (valid) { sortAndSlice.addLimitCondition(new ExpressionOp(OpTypes.LIMIT, e1, e2)); return; } throw Error.error(ErrorCode.X_42563, ErrorCode.M_INVALID_LIMIT); } private SortAndSlice XreadOrderBy() { SortAndSlice sortAndSlice = new SortAndSlice(); while (true) { Expression e; ExpressionOrderBy o; boolean isDesc = false; boolean nullsLast = false; e = XreadValueExpression(); o = new ExpressionOrderBy(e); if (token.tokenType == Tokens.DESC) { o.setDescending(); isDesc = true; read(); } else if (token.tokenType == Tokens.ASC) { read(); } if (database.sqlNullsOrder) { nullsLast = !database.sqlNullsFirst; } else { nullsLast = database.sqlNullsFirst == isDesc; } o.setNullsLast(nullsLast); if (token.tokenType == Tokens.NULLS) { read(); if (token.tokenType == Tokens.FIRST) { read(); o.setNullsLast(false); } else if (token.tokenType == Tokens.LAST) { read(); o.setNullsLast(true); } else { throw unexpectedToken(); } } sortAndSlice.addOrderExpression(o); if (token.tokenType == Tokens.COMMA) { read(); continue; } break; } return sortAndSlice; } protected RangeVariable readRangeVariableForDataChange(int operation) { Table table = readTableName(true); ExpressionPeriodOp appPeriodSpec = XreadQueryApplicationPeriodSpecOrNull(table); SimpleName alias = null; if (appPeriodSpec != null) { throw Error.error(ErrorCode.X_0A501); } if (operation != StatementTypes.TRUNCATE) { switch (token.tokenType) { case Tokens.OVERRIDING : break; case Tokens.AS : read(); checkIsNonCoreReservedIdentifier(); // fall through default : if (isNonCoreReservedIdentifier()) { if (!database.sqlSyntaxMys || operation != StatementTypes.INSERT) { alias = HsqlNameManager.getSimpleName( token.tokenString, isDelimitedIdentifier()); read(); } } } if (alias == null && lastSynonym != null) { alias = HsqlNameManager.getSimpleName(lastSynonym.name, lastSynonym.isNameQuoted); } } if (table.isView) { switch (operation) { case StatementTypes.MERGE : if (table.isTriggerUpdatable() && table.isTriggerInsertable()) { break; } if (table.isTriggerUpdatable() || table.isTriggerInsertable()) { // all or nothing } else if (table.isUpdatable() && table.isInsertable()) { break; } throw Error.error(ErrorCode.X_42545); case StatementTypes.UPDATE_WHERE : if (table.isTriggerUpdatable()) { break; } if (table.isUpdatable()) { break; } throw Error.error(ErrorCode.X_42545); case StatementTypes.DELETE_WHERE : if (table.isTriggerDeletable()) { break; } if (table.isUpdatable()) { break; } throw Error.error(ErrorCode.X_42545); case StatementTypes.INSERT : if (table.isTriggerInsertable()) { break; } if (table.isInsertable()) { break; } if (session.isProcessingScript()) { break; } throw Error.error(ErrorCode.X_42545); case StatementTypes.TRUNCATE : throw Error.error(ErrorCode.X_42545); } table = ((View) table).newDerivedTable(session, compileContext); } RangeVariable range = new RangeVariable(table, alias, null, null, compileContext); if (table.isSystemVersioned()) { ExpressionPeriodOp sysPeriodSpec = new ExpressionPeriodOp(); sysPeriodSpec.setSystemRangeVariable(session, range); range.setSystemPeriodCondition(sysPeriodSpec); } return range; } protected Table readNamedSubqueryOrNull() { if (!isSimpleName()) { return null; } TableDerived td = compileContext.getNamedSubQuery(token.tokenString); if (td == null) { return null; } read(); if (td.isRecompiled()) { td = td.newDerivedTable(session, compileContext); } return td; }
Creates a RangeVariable from the parse context.

/** * Creates a RangeVariable from the parse context. <p> */
protected RangeVariable readTableOrSubquery() { Table table = null; SimpleName alias = null; SimpleName[] columnNameList = null; OrderedHashSet columnList = null; ExpressionPeriodOp sysPeriodSpec = null; boolean joinedTable = false; boolean isLateral = false; boolean isTableName = false; switch (token.tokenType) { case Tokens.OPENBRACKET : { table = XreadTableSubqueryOrNull(false); if (table == null) { table = XreadJoinedTableAsSubqueryOrNull(); if (table == null) { table = XreadTableSubqueryOrNull(true); if (table == null) { throw unexpectedToken(); } break; } joinedTable = true; } break; } case Tokens.UNNEST : { Expression e = XreadCollectionDerivedTable(OpTypes.TABLE_SUBQUERY); table = e.getTable(); isLateral = true; break; } case Tokens.LATERAL : { Expression e = XreadLateralDerivedTable(); table = e.getTable(); isLateral = true; break; } case Tokens.TABLE : { Expression e = XreadTableFunctionDerivedTable(); table = e.getTable(); isLateral = true; break; } default : { table = readNamedSubqueryOrNull(); if (table == null) { table = readTableName(true); isTableName = true; // attach to range variable below sysPeriodSpec = XreadQuerySystemPeriodSpecOrNull(table); } if (table.isView()) { table = ((View) table).newDerivedTable(session, compileContext); } } } boolean hasAs = false; if (token.tokenType == Tokens.AS) { read(); checkIsNonCoreReservedIdentifier(); hasAs = true; } if (isNonCoreReservedIdentifier()) { boolean limit = token.tokenType == Tokens.LIMIT || token.tokenType == Tokens.OFFSET || token.tokenType == Tokens.FETCH; boolean minus = token.tokenType == Tokens.MINUS_EXCEPT; int position = getPosition(); alias = HsqlNameManager.getSimpleName(token.tokenString, isDelimitedIdentifier()); read(); if (token.tokenType == Tokens.OPENBRACKET) { columnList = new OrderedHashSet(); columnNameList = readColumnNameList(columnList); } else if (!hasAs && limit) { if (token.tokenType == Tokens.COLON || token.tokenType == Tokens.QUESTION || token.tokenType == Tokens.X_VALUE) { alias = null; rewind(position); } } else if (!hasAs && minus) { rewind(position); } } if (isTableName && alias == null && lastSynonym != null) { alias = HsqlNameManager.getSimpleName(lastSynonym.name, lastSynonym.isNameQuoted); } if (database.sqlSyntaxMss) { if (readIfThis(Tokens.WITH)) { readNestedParenthesisedTokens(); } } RangeVariable range; if (joinedTable) { range = new RangeVariableJoined(table, alias, columnList, columnNameList, compileContext); } else { range = new RangeVariable(table, alias, columnList, columnNameList, compileContext); if (sysPeriodSpec != null) { sysPeriodSpec.setSystemRangeVariable(session, range); range.setSystemPeriodCondition(sysPeriodSpec); } } if (isLateral) { range.isLateral = true; } return range; } private Expression readAggregateFunctionOrNull() { int position = getPosition(); int tokenT = token.tokenType; Expression expr; read(); if (token.tokenType != Tokens.OPENBRACKET) { rewind(position); return null; } readThis(Tokens.OPENBRACKET); expr = readAggregateExpression(tokenT); readThis(Tokens.CLOSEBRACKET); readFilterClause(expr); return expr; } private void readFilterClause(Expression e) { ExpressionLogical condition = XreadFilterExpressionOrNull(); if (condition != null) { e.setCondition(condition); } } ExpressionLogical XreadFilterExpressionOrNull() { int position = getPosition(); ExpressionLogical condition = null; if (token.tokenType == Tokens.FILTER) { read(); if (token.tokenType != Tokens.OPENBRACKET) { rewind(position); return null; } readThis(Tokens.OPENBRACKET); readThis(Tokens.WHERE); condition = (ExpressionLogical) XreadBooleanValueExpression(); readThis(Tokens.CLOSEBRACKET); } return condition; } private Expression readAggregateExpression(int tokenT) { int type = ParserDQL.getExpressionType(tokenT); boolean distinct = false; boolean all = false; SortAndSlice sort = null; String separator = null; if (token.tokenType == Tokens.DISTINCT) { distinct = true; read(); } else if (token.tokenType == Tokens.ALL) { all = true; read(); } int position = getPosition(); Expression e = XreadValueExpression(); switch (type) { case OpTypes.COUNT : if (e.getType() == OpTypes.MULTICOLUMN) { if (((ExpressionColumn) e).tableName != null) { throw unexpectedToken(); } if (all || distinct) { throw unexpectedToken(); } e.opType = OpTypes.ASTERISK; } else { if (token.tokenType == Tokens.COMMA) { rewind(position); e = XreadRowElementList(false); } } break; case OpTypes.STDDEV_POP : case OpTypes.STDDEV_SAMP : case OpTypes.VAR_POP : case OpTypes.VAR_SAMP : if (all || distinct) { throw unexpectedToken(all ? Tokens.T_ALL : Tokens.T_DISTINCT); } break; case OpTypes.ARRAY_AGG : case OpTypes.GROUP_CONCAT : { if (token.tokenType == Tokens.ORDER) { read(); readThis(Tokens.BY); sort = XreadOrderBy(); } if (type == OpTypes.GROUP_CONCAT) { if (token.tokenType == Tokens.SEPARATOR) { read(); checkIsQuotedString(); separator = (String) token.tokenValue; read(); } } return new ExpressionArrayAggregate(type, distinct, e, sort, separator); } case OpTypes.MEDIAN : { return new ExpressionArrayAggregate(type, distinct, e, sort, separator); } default : if (e.getType() == OpTypes.MULTICOLUMN || e.getType() == OpTypes.ASTERISK) { throw unexpectedToken(Tokens.T_ASTERISK); } } Expression aggregateExp = new ExpressionAggregate(type, distinct, e); return aggregateExp; } //-------------------------------------- // returns null // := <unsigned literal> | <general value specification> Expression XreadValueSpecificationOrNull() { Expression e = null; boolean minus = false; switch (token.tokenType) { case Tokens.PLUS_OP : read(); break; case Tokens.MINUS_OP : read(); minus = true; break; default : } e = XreadUnsignedValueSpecificationOrNull(); if (e == null) { return null; } if (minus) { e = new ExpressionArithmetic(OpTypes.NEGATE, e); } return e; } // returns null // <unsigned literal> | <general value specification> Expression XreadUnsignedValueSpecificationOrNull() { Expression e; switch (token.tokenType) { case Tokens.TRUE : read(); return Expression.EXPR_TRUE; case Tokens.FALSE : read(); return Expression.EXPR_FALSE; case Tokens.DEFAULT : if (compileContext.contextuallyTypedExpression) { read(); e = new ExpressionColumn(OpTypes.DEFAULT); return e; } break; case Tokens.NULL : e = new ExpressionValue(null, null); read(); return e; case Tokens.X_VALUE : e = new ExpressionValue(token.tokenValue, token.dataType); read(); return e; case Tokens.X_DELIMITED_IDENTIFIER : case Tokens.X_IDENTIFIER : if (!token.isHostParameter) { return null; } return null; case Tokens.COLON : read(); if (token.tokenType == Tokens.X_DELIMITED_IDENTIFIER || token.tokenType == Tokens.X_IDENTIFIER) {} else { throw unexpectedToken(Tokens.T_COLON); } // fall through case Tokens.QUESTION : ExpressionColumn p = new ExpressionColumn(OpTypes.DYNAMIC_PARAM); compileContext.addParameter(p, getPosition()); read(); return p; case Tokens.COLLATION : return XreadCurrentCollationSpec(); case Tokens.VALUE : case Tokens.CURRENT_CATALOG : case Tokens.CURRENT_DEFAULT_TRANSFORM_GROUP : case Tokens.CURRENT_PATH : case Tokens.CURRENT_ROLE : case Tokens.CURRENT_SCHEMA : case Tokens.CURRENT_TRANSFORM_GROUP_FOR_TYPE : case Tokens.CURRENT_USER : case Tokens.SESSION_USER : case Tokens.SYSTEM_USER : case Tokens.USER : FunctionSQL function = FunctionSQL.newSQLFunction(token.tokenString, compileContext); if (function == null) { return null; } return readSQLFunction(function); // read SQL parameter reference } return null; } // <unsigned literal> | <dynamic parameter> | <variable> Expression XreadSimpleValueSpecificationOrNull() { Expression e; switch (token.tokenType) { case Tokens.X_VALUE : e = new ExpressionValue(token.tokenValue, token.dataType); read(); return e; case Tokens.COLON : read(); if (token.tokenType == Tokens.X_DELIMITED_IDENTIFIER || token.tokenType == Tokens.X_IDENTIFIER) {} else { throw unexpectedToken(Tokens.T_COLON); } // fall through case Tokens.QUESTION : ExpressionColumn p = new ExpressionColumn(OpTypes.DYNAMIC_PARAM); compileContext.addParameter(p, getPosition()); read(); return p; case Tokens.X_IDENTIFIER : case Tokens.X_DELIMITED_IDENTIFIER : checkValidCatalogName(token.namePrePrePrefix); e = new ExpressionColumn(token.namePrePrefix, token.namePrefix, token.tokenString); read(); return e; default : return null; } } // combined <value expression primary> and <predicate> // exclusively called // <explicit row value constructor> needed for predicate Expression XreadAllTypesValueExpressionPrimary(boolean isBoolean) { Expression e = null; int position = getPosition(); switch (token.tokenType) { case Tokens.EXISTS : case Tokens.UNIQUE : if (isBoolean) { return XreadPredicate(); } break; case Tokens.PERIOD : if (isBoolean) { break; } read(); if (readIfThis(Tokens.OPENBRACKET)) { e = XreadRowElementList(true); if (e.nodes.length != 2) { throw Error.error(ErrorCode.X_42564); } e = new ExpressionPeriod(e); readThis(Tokens.CLOSEBRACKET); } else { rewind(position); e = XreadSimpleValueExpressionPrimary(); if (e != null) { e = XreadArrayElementReference(e); } } break; case Tokens.ROW : if (isBoolean) { break; } read(); readThis(Tokens.OPENBRACKET); e = XreadRowElementList(true); readThis(Tokens.CLOSEBRACKET); break; default : e = XreadSimpleValueExpressionPrimary(); if (e != null) { e = XreadArrayElementReference(e); } } if (e == null) { if (token.tokenType == Tokens.ROW) { read(); checkIsThis(Tokens.OPENBRACKET); } else if (token.tokenType == Tokens.PERIOD) { read(); readThis(Tokens.OPENBRACKET); e = XreadRowElementList(true); if (e.nodes.length != 2) { throw Error.error(ErrorCode.X_42564); } e = new ExpressionPeriod(e); readThis(Tokens.CLOSEBRACKET); } if (token.tokenType == Tokens.OPENBRACKET) { read(); e = XreadRowElementList(true); readThis(Tokens.CLOSEBRACKET); } } if (isBoolean && e != null) { e = XreadPredicateRightPart(e); } return e; } // doesn't return null // <value expression primary> ::= <parenthesized value expression> // | <nonparenthesized value expression primary> Expression XreadValueExpressionPrimary() { Expression e; e = XreadSimpleValueExpressionPrimary(); if (e != null) { e = XreadArrayElementReference(e); return e; } if (token.tokenType == Tokens.OPENBRACKET) { read(); e = XreadValueExpression(); readThis(Tokens.CLOSEBRACKET); } else { return null; } return e; } // returns null // <row value special case> :== this // <boolean predicand> :== this | <parenthesized boolean value expression> Expression XreadSimpleValueExpressionPrimary() { Expression e; e = XreadUnsignedValueSpecificationOrNull(); if (e != null) { return e; } int position = getPosition(); switch (token.tokenType) { case Tokens.OPENBRACKET : read(); int subqueryPosition = getPosition(); readOpenBrackets(); switch (token.tokenType) { case Tokens.TABLE : case Tokens.VALUES : case Tokens.SELECT : TableDerived td = null; rewind(subqueryPosition); try { td = XreadSubqueryTableBody( OpTypes.SCALAR_SUBQUERY); readThis(Tokens.CLOSEBRACKET); } catch (HsqlException ex) { ex.setLevel(compileContext.subqueryDepth); if (lastError == null || lastError.getLevel() < ex.getLevel()) { lastError = ex; } rewind(position); return null; } if (td.queryExpression != null) { if (td.queryExpression.isSingleColumn()) { e = new Expression(OpTypes.SCALAR_SUBQUERY, td); } else { e = new Expression(OpTypes.ROW_SUBQUERY, td); } } if (e != null) { return e; } // fall through default : rewind(position); return null; } case Tokens.ASTERISK : e = new ExpressionColumn(token.namePrePrefix, token.namePrefix); getRecordedToken().setExpression(e); read(); return e; case Tokens.LEAST : { e = readLeastExpressionOrNull(); if (e != null) { return e; } break; } case Tokens.GREATEST : { e = readGreatestExpressionOrNull(); if (e != null) { return e; } break; } case Tokens.DECODE : { e = readDecodeExpressionOrNull(); if (e != null) { return e; } break; } case Tokens.CONCAT_WORD : { e = readConcatExpressionOrNull(); if (e != null) { return e; } break; } case Tokens.CONCAT_WS : { e = readConcatSeparatorExpressionOrNull(); if (e != null) { return e; } break; } case Tokens.IF : case Tokens.CASEWHEN : { e = readCaseWhenExpressionOrNull(); if (e != null) { return e; } break; } case Tokens.CASE : return readCaseExpression(); case Tokens.NULLIF : return readNullIfExpression(); case Tokens.COALESCE : return readCoalesceExpression(); case Tokens.IFNULL : case Tokens.ISNULL : { e = readIfNullExpressionOrNull(); if (e != null) { return e; } break; } case Tokens.NVL2 : { e = readIfNull2ExpressionOrNull(); if (e != null) { return e; } break; } case Tokens.CAST : e = readCastExpression(); if (e != null) { return e; } break; case Tokens.CONVERT : { e = readConvertExpressionOrNull(); if (e != null) { return e; } break; } case Tokens.DATE : case Tokens.TIME : case Tokens.TIMESTAMP : case Tokens.INTERVAL : e = readDateTimeIntervalLiteral(session); if (e != null) { return e; } break; case Tokens.ARRAY : return readCollection(OpTypes.ARRAY); case Tokens.COUNT : case Tokens.AVG : case Tokens.MAX : case Tokens.MIN : case Tokens.SUM : case Tokens.ANY : case Tokens.SOME : case Tokens.EVERY : case Tokens.STDDEV_POP : case Tokens.STDDEV_SAMP : case Tokens.VAR_POP : case Tokens.VAR_SAMP : case Tokens.GROUP_CONCAT : case Tokens.ARRAY_AGG : case Tokens.MEDIAN : e = readAggregateFunctionOrNull(); // general set function if (e != null) { return e; } break; case Tokens.NEXT : { e = readSequenceExpressionOrNull(OpTypes.SEQUENCE); if (e != null) { return e; } break; } case Tokens.PREVVAL : case Tokens.CURRENT : { e = readSequenceExpressionOrNull(OpTypes.SEQUENCE_CURRENT); if (e != null) { return e; } break; } case Tokens.CURRVAL : { if (database.sqlSyntaxPgs) { read(); readThis(Tokens.OPENBRACKET); String spec = readQuotedString(); Scanner scanner = session.getScanner(); scanner.reset(session, spec); scanner.scanNext(); String schemaName = session.getSchemaName(scanner.token.namePrefix); NumberSequence sequence = database.schemaManager.getSequence( scanner.token.tokenString, schemaName, true); e = new ExpressionColumn(sequence, OpTypes.SEQUENCE_CURRENT); readThis(Tokens.CLOSEBRACKET); return e; } break; } case Tokens.LASTVAL : { if (database.sqlSyntaxPgs) { read(); readThis(Tokens.OPENBRACKET); readThis(Tokens.CLOSEBRACKET); return FunctionCustom.newCustomFunction(session, Tokens.T_IDENTITY, Tokens.IDENTITY); } break; } case Tokens.NEXTVAL : { if (database.sqlSyntaxPgs) { return readNextvalFunction(); } else if (database.sqlSyntaxDb2) { e = readSequenceExpressionOrNull(OpTypes.SEQUENCE); if (e != null) { return e; } } break; } case Tokens.ROW_NUMBER : { read(); if (token.tokenType == Tokens.OPENBRACKET) { read(); readThis(Tokens.CLOSEBRACKET); readThis(Tokens.OVER); readThis(Tokens.OPENBRACKET); readThis(Tokens.CLOSEBRACKET); } else { rewind(position); break; } return new ExpressionColumn(OpTypes.ROWNUM); } case Tokens.ROWNUM : { read(); if (token.tokenType == Tokens.OPENBRACKET) { read(); if (token.tokenType == Tokens.CLOSEBRACKET) { read(); } else { rewind(position); break; } } else if (!database.sqlSyntaxOra && !database.sqlSyntaxDb2) { rewind(position); break; } return new ExpressionColumn(OpTypes.ROWNUM); } case Tokens.LEFT : case Tokens.RIGHT : // CLI function names break; case Tokens.TABLE : { read(); readThis(Tokens.OPENBRACKET); TableDerived td = XreadSubqueryTableBody(OpTypes.TABLE_SUBQUERY); readThis(Tokens.CLOSEBRACKET); return new Expression(OpTypes.TABLE_SUBQUERY, td); } default : if (isCoreReservedKey()) { throw unexpectedToken(); } } e = readColumnOrFunctionExpression(); if (e.isSelfAggregate()) { readFilterClause(e); } return e; } Expression readNextvalFunction() { read(); readThis(Tokens.OPENBRACKET); String spec = readQuotedString(); Scanner scanner = session.getScanner(); scanner.reset(session, spec); scanner.scanNext(); String schemaName = session.getSchemaName(scanner.token.namePrefix); NumberSequence sequence = database.schemaManager.getSequence(scanner.token.tokenString, schemaName, true); Expression e = new ExpressionColumn(sequence, OpTypes.SEQUENCE); readThis(Tokens.CLOSEBRACKET); return e; } // OK - composite production - // <numeric primary> <character primary> <binary primary> <datetime primary> <interval primary> Expression XreadAllTypesPrimary(boolean boole) { Expression e = null; switch (token.tokenType) { case Tokens.SUBSTRING : case Tokens.SUBSTRING_REGEX : case Tokens.LOWER : case Tokens.UPPER : case Tokens.TRANSLATE_REGEX : case Tokens.TRIM : case Tokens.OVERLAY : case Tokens.NORMALIZE : // case Tokens.POSITION : case Tokens.OCCURRENCES_REGEX : case Tokens.POSITION_REGEX : case Tokens.EXTRACT : case Tokens.CHAR_LENGTH : case Tokens.CHARACTER_LENGTH : case Tokens.OCTET_LENGTH : case Tokens.CARDINALITY : case Tokens.ARRAY_MAX_CARDINALITY : case Tokens.MAX_CARDINALITY : case Tokens.ABS : case Tokens.MOD : case Tokens.LN : case Tokens.EXP : case Tokens.POWER : case Tokens.SQRT : case Tokens.FLOOR : case Tokens.CEILING : case Tokens.CEIL : case Tokens.WIDTH_BUCKET : FunctionSQL function = FunctionSQL.newSQLFunction(token.tokenString, compileContext); if (function == null) { throw unsupportedFeature(); } e = readSQLFunction(function); if (e != null) { break; } // fall through default : e = XreadAllTypesValueExpressionPrimary(boole); } e = XreadModifier(e); return e; } Expression XreadModifier(Expression e) { int position = getPosition(); switch (token.tokenType) { case Tokens.AT : { read(); Expression e1 = null; if (token.tokenType == Tokens.LOCAL) { read(); } else if (token.tokenType == Tokens.TIME) { readThis(Tokens.TIME); readThis(Tokens.ZONE); e1 = XreadValueExpressionPrimary(); switch (token.tokenType) { case Tokens.YEAR : case Tokens.MONTH : case Tokens.DAY : case Tokens.HOUR : case Tokens.MINUTE : case Tokens.SECOND : { IntervalType type = readIntervalType(session, false); if (e1.getType() == OpTypes.SUBTRACT) { e1.dataType = type; } else { e1 = new ExpressionOp(e1, type); } break; } default : } } else { rewind(position); return e; } e = new ExpressionOp(OpTypes.ZONE_MODIFIER, e, e1); break; } case Tokens.YEAR : case Tokens.MONTH : case Tokens.DAY : case Tokens.HOUR : case Tokens.MINUTE : case Tokens.SECOND : { IntervalType type = readIntervalType(session, true); if (e.getType() == OpTypes.SUBTRACT) { e.dataType = type; } else { e = new ExpressionOp(e, type); } break; } case Tokens.COLLATE : { read(); Collation collation = database.schemaManager.getCollation(session, token.tokenString, token.namePrefix); e.setCollation(collation); read(); } } return e; } Expression XreadValueExpressionWithContext() { Expression e; compileContext.contextuallyTypedExpression = true; e = XreadValueExpression(); compileContext.contextuallyTypedExpression = false; return e; }
::= | |
/** * <value expression> ::= * <common value expression> * | <boolean value expression> * | <row value expression> * */
Expression XreadValueExpression() { Expression e = XreadAllTypesCommonValueExpression(true); if (token.tokenType == Tokens.LEFTBRACKET) { read(); Expression e1 = XreadNumericValueExpression(); readThis(Tokens.RIGHTBRACKET); e = new ExpressionAccessor(e, e1); } return e; } // union of <numeric | datetime | string | interval value expression> Expression XreadRowOrCommonValueExpression() { return XreadAllTypesCommonValueExpression(false); } // union of <numeric | datetime | string | interval | boolean value expression> // no <row value expression> and no <predicate> Expression XreadAllTypesCommonValueExpression(boolean boole) { Expression e = XreadAllTypesTerm(boole); int type = 0; boolean end = false; while (true) { switch (token.tokenType) { case Tokens.PLUS_OP : type = OpTypes.ADD; boole = false; break; case Tokens.MINUS_OP : type = OpTypes.SUBTRACT; boole = false; break; case Tokens.CONCAT_OP : type = OpTypes.CONCAT; boole = false; break; case Tokens.OR : if (boole) { type = OpTypes.OR; break; } // fall through default : end = true; break; } if (end) { break; } read(); Expression a = e; e = XreadAllTypesTerm(boole); e = boole ? new ExpressionLogical(type, a, e) : new ExpressionArithmetic(type, a, e); } return e; } Expression XreadAllTypesTerm(boolean boole) { Expression e = XreadAllTypesFactor(boole); int type = 0; boolean end = false; while (true) { switch (token.tokenType) { case Tokens.ASTERISK : type = OpTypes.MULTIPLY; boole = false; break; case Tokens.DIVIDE_OP : type = OpTypes.DIVIDE; boole = false; break; case Tokens.AND : if (boole) { type = OpTypes.AND; break; } // fall through default : end = true; break; } if (end) { break; } read(); Expression a = e; e = XreadAllTypesFactor(boole); if (e == null) { throw unexpectedToken(); } e = boole ? new ExpressionLogical(type, a, e) : new ExpressionArithmetic(type, a, e); } return e; } Expression XreadAllTypesFactor(boolean boole) { Expression e; boolean minus = false; boolean not = false; boolean unknown = false; switch (token.tokenType) { case Tokens.PLUS_OP : read(); boole = false; break; case Tokens.MINUS_OP : read(); boole = false; minus = true; break; case Tokens.NOT : if (boole) { read(); not = true; } break; default : } e = XreadAllTypesPrimary(boole); if (boole && token.tokenType == Tokens.IS) { read(); if (token.tokenType == Tokens.NOT) { read(); not = !not; } if (token.tokenType == Tokens.TRUE) { read(); } else if (token.tokenType == Tokens.FALSE) { read(); not = !not; } else if (token.tokenType == Tokens.UNKNOWN) { read(); unknown = true; } else { throw unexpectedToken(); } } if (unknown) { e = new ExpressionLogical(OpTypes.IS_NULL, e); } else if (minus) { e = new ExpressionArithmetic(OpTypes.NEGATE, e); } else if (not) { e = new ExpressionLogical(OpTypes.NOT, e); } return e; } Expression XreadStringValueExpression() { return XreadCharacterValueExpression(); // XreadBinaryValueExpression(); } Expression XreadCharacterValueExpression() { Expression e = XreadCharacterPrimary(); Collation collation = readCollateClauseOrNull(); while (token.tokenType == Tokens.CONCAT_OP) { read(); Expression a = e; e = XreadCharacterPrimary(); collation = readCollateClauseOrNull(); e = new ExpressionArithmetic(OpTypes.CONCAT, a, e); } return e; } Expression XreadCharacterPrimary() { switch (token.tokenType) { case Tokens.SUBSTRING : // case Token.SUBSTRING_REGEX : case Tokens.LOWER : case Tokens.UPPER : // case Token.TRANSLATE_REGEX : case Tokens.TRIM : case Tokens.OVERLAY : // case Token.NORMALIZE : FunctionSQL function = FunctionSQL.newSQLFunction(token.tokenString, compileContext); Expression e = readSQLFunction(function); if (e != null) { return e; } } return XreadValueExpressionPrimary(); } Expression XreadNumericPrimary() { switch (token.tokenType) { case Tokens.POSITION : // case Token.OCCURRENCES_REGEX : // case Token.POSITION_REGEX : case Tokens.EXTRACT : case Tokens.CHAR_LENGTH : case Tokens.CHARACTER_LENGTH : case Tokens.OCTET_LENGTH : case Tokens.CARDINALITY : case Tokens.ABS : case Tokens.MOD : case Tokens.LN : case Tokens.EXP : case Tokens.POWER : case Tokens.SQRT : case Tokens.FLOOR : case Tokens.CEILING : case Tokens.CEIL : case Tokens.WIDTH_BUCKET : FunctionSQL function = FunctionSQL.newSQLFunction(token.tokenString, compileContext); if (function == null) { throw unexpectedToken(); } Expression e = readSQLFunction(function); if (e != null) { return e; } } return XreadValueExpressionPrimary(); } Expression XreadNumericValueExpression() { Expression e = XreadTerm(); while (true) { int type; if (token.tokenType == Tokens.PLUS_OP) { type = OpTypes.ADD; } else if (token.tokenType == Tokens.MINUS_OP) { type = OpTypes.SUBTRACT; } else { break; } read(); Expression a = e; e = XreadTerm(); e = new ExpressionArithmetic(type, a, e); } return e; } Expression XreadTerm() { Expression e = XreadFactor(); int type; while (true) { if (token.tokenType == Tokens.ASTERISK) { type = OpTypes.MULTIPLY; } else if (token.tokenType == Tokens.DIVIDE_OP) { type = OpTypes.DIVIDE; } else { break; } read(); Expression a = e; e = XreadFactor(); if (e == null) { throw unexpectedToken(); } e = new ExpressionArithmetic(type, a, e); } return e; } Expression XreadFactor() { Expression e; boolean minus = false; if (token.tokenType == Tokens.PLUS_OP) { read(); } else if (token.tokenType == Tokens.MINUS_OP) { read(); minus = true; } e = XreadNumericPrimary(); if (e == null) { return null; } if (minus) { e = new ExpressionArithmetic(OpTypes.NEGATE, e); } return e; } Expression XreadDatetimeValueExpression() { Expression e = XreadDateTimeIntervalTerm(); while (true) { int type; if (token.tokenType == Tokens.PLUS_OP) { type = OpTypes.ADD; } else if (token.tokenType == Tokens.MINUS_OP) { type = OpTypes.SUBTRACT; } else { break; } read(); Expression a = e; e = XreadDateTimeIntervalTerm(); e = new ExpressionArithmetic(type, a, e); } return e; } Expression XreadIntervalValueExpression() { Expression e = XreadDateTimeIntervalTerm(); while (true) { int type; if (token.tokenType == Tokens.PLUS_OP) { type = OpTypes.ADD; } else if (token.tokenType == Tokens.MINUS_OP) { type = OpTypes.SUBTRACT; } else { break; } read(); Expression a = e; e = XreadDateTimeIntervalTerm(); e = new ExpressionArithmetic(type, a, e); } return e; } Expression XreadDateTimeIntervalTerm() { switch (token.tokenType) { case Tokens.CURRENT_DATE : case Tokens.CURRENT_TIME : case Tokens.CURRENT_TIMESTAMP : case Tokens.LOCALTIME : case Tokens.LOCALTIMESTAMP : // case Tokens.ABS : FunctionSQL function = FunctionSQL.newSQLFunction(token.tokenString, compileContext); if (function == null) { throw unexpectedToken(); } return readSQLFunction(function); default : } return XreadValueExpressionPrimary(); } // returns null Expression XreadDateTimeValueFunctionOrNull() { FunctionSQL function = null; switch (token.tokenType) { case Tokens.CURRENT_DATE : case Tokens.CURRENT_TIME : case Tokens.CURRENT_TIMESTAMP : case Tokens.LOCALTIME : case Tokens.LOCALTIMESTAMP : function = FunctionSQL.newSQLFunction(token.tokenString, compileContext); break; case Tokens.SYSTIMESTAMP : case Tokens.NOW : case Tokens.TODAY : case Tokens.SYSDATE : function = FunctionCustom.newCustomFunction(session, token.tokenString, token.tokenType); if (function == null) { return null; } break; default : return null; } if (function == null) { throw unexpectedToken(); } return readSQLFunction(function); } Expression XreadBooleanValueExpression() { try { Expression e = XreadBooleanTermOrNull(); if (e == null) { throw Error.error(ErrorCode.X_42568); } while (true) { int type; if (token.tokenType == Tokens.OR) { type = OpTypes.OR; } else { break; } read(); Expression a = e; e = XreadBooleanTermOrNull(); if (e == null) { throw Error.error(ErrorCode.X_42568); } e = new ExpressionLogical(type, a, e); } if (e == null) { throw Error.error(ErrorCode.X_42568); } return e; } catch (HsqlException ex) { ex.setLevel(compileContext.subqueryDepth); if (lastError != null && lastError.getLevel() >= ex.getLevel()) { ex = lastError; lastError = null; } throw ex; } } Expression XreadBooleanTermOrNull() { Expression e = XreadBooleanFactorOrNull(); if (e == null) { return null; } int type; while (true) { if (token.tokenType == Tokens.AND) { type = OpTypes.AND; } else { break; } read(); Expression a = e; e = XreadBooleanFactorOrNull(); if (e == null) { throw unexpectedToken(); } e = new ExpressionLogical(type, a, e); } return e; } Expression XreadBooleanFactorOrNull() { Expression e; boolean not = false; if (token.tokenType == Tokens.NOT) { read(); not = true; } e = XreadBooleanTestOrNull(); if (e == null) { return null; } if (not) { e = new ExpressionLogical(OpTypes.NOT, e); } return e; } Expression XreadBooleanTestOrNull() { boolean unknown = false; boolean isNot = false; Expression e = XreadBooleanPrimaryOrNull(); if (e == null) { return e; } if (token.tokenType == Tokens.IS) { read(); if (token.tokenType == Tokens.NOT) { read(); isNot = true; } if (token.tokenType == Tokens.TRUE) { read(); } else if (token.tokenType == Tokens.FALSE) { read(); isNot = !isNot; } else if (token.tokenType == Tokens.UNKNOWN) { read(); unknown = true; } else { throw unexpectedToken(); } } if (unknown) { e = new ExpressionLogical(OpTypes.IS_NULL, e); } if (isNot) { e = new ExpressionLogical(OpTypes.NOT, e); } return e; } // <boolean primary> ::= <predicate> | <boolean predicand> Expression XreadBooleanPrimaryOrNull() { Expression e = null; int position; switch (token.tokenType) { case Tokens.EXISTS : case Tokens.UNIQUE : return XreadPredicate(); case Tokens.ROW : read(); readThis(Tokens.OPENBRACKET); e = XreadRowElementList(true); readThis(Tokens.CLOSEBRACKET); break; default : position = getPosition(); try { e = XreadAllTypesCommonValueExpression(false); } catch (HsqlException ex) { ex.setLevel(compileContext.subqueryDepth); if (lastError == null || lastError.getLevel() < ex.getLevel()) { lastError = ex; } rewind(position); } } if (e == null && token.tokenType == Tokens.OPENBRACKET) { read(); position = getPosition(); try { e = XreadRowElementList(true); readThis(Tokens.CLOSEBRACKET); } catch (HsqlException ex) { ex.setLevel(compileContext.subqueryDepth); if (lastError == null || lastError.getLevel() < ex.getLevel()) { lastError = ex; } rewind(position); e = XreadBooleanValueExpression(); readThis(Tokens.CLOSEBRACKET); } } if (e != null) { e = XreadPredicateRightPart(e); } return e; } // similar to <value expression primary> Expression XreadBooleanPredicand() { Expression e; if (token.tokenType == Tokens.OPENBRACKET) { read(); e = XreadBooleanValueExpression(); readThis(Tokens.CLOSEBRACKET); return e; } else { e = XreadSimpleValueExpressionPrimary(); if (e != null) { e = XreadArrayElementReference(e); } return e; } } Expression XreadPredicate() { switch (token.tokenType) { case Tokens.EXISTS : { read(); Expression s = XreadTableSubquery(OpTypes.EXISTS); return new ExpressionLogical(OpTypes.EXISTS, s); } case Tokens.UNIQUE : { read(); Expression s = XreadTableSubquery(OpTypes.UNIQUE); return new ExpressionLogical(OpTypes.UNIQUE, s); } default : { Expression a = XreadRowValuePredicand(); return XreadPredicateRightPart(a); } } } Expression XreadPredicateRightPart(final Expression l) { boolean hasNot = false; boolean immediately = false; ExpressionLogical e = null; Expression r; int position = getPosition(); if (token.tokenType == Tokens.NOT) { read(); hasNot = true; } // valid for PRECEDES and SUCCEEDS predicates if (token.tokenType == Tokens.IMMEDIATELY) { read(); if (token.tokenType != Tokens.PRECEDES && token.tokenType != Tokens.SUCCEEDS) { throw unexpectedToken(); } immediately = true; } switch (token.tokenType) { case Tokens.IS : { if (hasNot) { throw unexpectedToken(); } read(); if (token.tokenType == Tokens.NOT) { hasNot = true; read(); } if (token.tokenType == Tokens.NULL) { read(); if (hasNot) { e = new ExpressionLogical(OpTypes.IS_NOT_NULL, l); hasNot = false; } else { e = new ExpressionLogical(OpTypes.IS_NULL, l); } break; } if (token.tokenType == Tokens.DISTINCT) { read(); readThis(Tokens.FROM); r = XreadRowValuePredicand(); e = new ExpressionLogical(OpTypes.NOT_DISTINCT, l, r); hasNot = !hasNot; break; } rewind(position); return l; } case Tokens.LIKE : { e = XreadLikePredicateRightPart(l); e.noOptimisation = isCheckOrTriggerCondition; break; } case Tokens.BETWEEN : { e = XreadBetweenPredicateRightPart(l); break; } case Tokens.IN : { e = XreadInPredicateRightPart(l); e.noOptimisation = isCheckOrTriggerCondition; break; } case Tokens.CONTAINS : { if (hasNot) { throw unexpectedToken(); } e = XreadPeriodPredicateRightPart(OpTypes.RANGE_CONTAINS, l); break; } case Tokens.EQUALS : { if (hasNot) { throw unexpectedToken(); } e = XreadPeriodPredicateRightPart(OpTypes.RANGE_EQUALS, l); break; } case Tokens.OVERLAPS : { if (hasNot) { throw unexpectedToken(); } e = XreadPeriodPredicateRightPart(OpTypes.RANGE_OVERLAPS, l); break; } case Tokens.PRECEDES : { if (hasNot) { throw unexpectedToken(); } if (immediately) { e = XreadPeriodPredicateRightPart( OpTypes.RANGE_IMMEDIATELY_PRECEDES, l); } else { e = XreadPeriodPredicateRightPart(OpTypes.RANGE_PRECEDES, l); } break; } case Tokens.SUCCEEDS : { if (hasNot) { throw unexpectedToken(); } if (immediately) { e = XreadPeriodPredicateRightPart( OpTypes.RANGE_IMMEDIATELY_SUCCEEDS, l); } else { e = XreadPeriodPredicateRightPart(OpTypes.RANGE_SUCCEEDS, l); } break; } case Tokens.EQUALS_OP : case Tokens.GREATER_EQUALS : case Tokens.GREATER_OP : case Tokens.LESS_OP : case Tokens.LESS_EQUALS : case Tokens.NOT_EQUALS : { if (hasNot) { throw unexpectedToken(); } int type = getExpressionType(token.tokenType); read(); switch (token.tokenType) { case Tokens.ANY : case Tokens.SOME : case Tokens.ALL : e = XreadQuantifiedComparisonRightPart(type, l); break; default : { Expression row = XreadRowValuePredicand(); e = new ExpressionLogical(type, l, row); break; } } break; } case Tokens.MATCH : { e = XreadMatchPredicateRightPart(l); break; } default : { if (hasNot) { throw unexpectedToken(); } return l; } } if (hasNot) { e = new ExpressionLogical(OpTypes.NOT, e); } return e; } private ExpressionLogical XreadBetweenPredicateRightPart( final Expression a) { boolean symmetric = false; read(); if (token.tokenType == Tokens.ASYMMETRIC) { read(); } else if (token.tokenType == Tokens.SYMMETRIC) { symmetric = true; read(); } Expression left = XreadRowValuePredicand(); readThis(Tokens.AND); Expression right = XreadRowValuePredicand(); Expression l = new ExpressionLogical(OpTypes.GREATER_EQUAL, a, left); Expression r = new ExpressionLogical(OpTypes.SMALLER_EQUAL, a, right); ExpressionLogical leftToRight = new ExpressionLogical(OpTypes.AND, l, r); if (symmetric) { l = new ExpressionLogical(OpTypes.SMALLER_EQUAL, a, left); r = new ExpressionLogical(OpTypes.GREATER_EQUAL, a, right); Expression rightToLeft = new ExpressionLogical(OpTypes.AND, l, r); return new ExpressionLogical(OpTypes.OR, leftToRight, rightToLeft); } else { return leftToRight; } } private ExpressionLogical XreadQuantifiedComparisonRightPart(int exprType, Expression l) { int tokenT = token.tokenType; int exprSubType = 0; Expression e; switch (token.tokenType) { case Tokens.ANY : case Tokens.SOME : exprSubType = OpTypes.ANY_QUANTIFIED; break; case Tokens.ALL : exprSubType = OpTypes.ALL_QUANTIFIED; break; default : throw Error.runtimeError(ErrorCode.U_S0500, "ParserDQL"); } read(); readThis(Tokens.OPENBRACKET); int position = getPosition(); readOpenBrackets(); switch (token.tokenType) { case Tokens.WITH : case Tokens.TABLE : case Tokens.VALUES : case Tokens.SELECT : rewind(position); TableDerived td = XreadSubqueryTableBody(OpTypes.IN); e = new Expression(OpTypes.TABLE_SUBQUERY, td); readThis(Tokens.CLOSEBRACKET); break; default : rewind(position); e = readAggregateExpression(tokenT); readThis(Tokens.CLOSEBRACKET); readFilterClause(e); } ExpressionLogical r = new ExpressionLogical(exprType, l, e); r.setSubType(exprSubType); return r; } private ExpressionLogical XreadInPredicateRightPart(Expression l) { int degree = l.getDegree(); Expression e = null; read(); readThis(Tokens.OPENBRACKET); int position = getPosition(); int brackets = readOpenBrackets(); switch (token.tokenType) { case Tokens.UNNEST : e = XreadCollectionDerivedTable(OpTypes.IN); readThis(Tokens.CLOSEBRACKET); readCloseBrackets(brackets); break; case Tokens.WITH : case Tokens.TABLE : case Tokens.VALUES : case Tokens.SELECT : { rewind(position); TableDerived td = XreadSubqueryTableBody(OpTypes.IN); e = new Expression(OpTypes.TABLE_SUBQUERY, td); readThis(Tokens.CLOSEBRACKET); break; } default : { rewind(position); e = XreadInValueListConstructor(degree); readThis(Tokens.CLOSEBRACKET); break; } } ExpressionLogical r; if (isCheckOrTriggerCondition) { r = new ExpressionLogical(OpTypes.IN, l, e); } else { r = new ExpressionLogical(OpTypes.EQUAL, l, e); r.setSubType(OpTypes.ANY_QUANTIFIED); } return r; } Expression XreadInValueList(int degree) { HsqlArrayList list = new HsqlArrayList(); while (true) { Expression e = XreadValueExpression(); if (e.getType() != OpTypes.ROW) { e = new Expression(OpTypes.ROW, new Expression[]{ e }); } list.add(e); if (token.tokenType == Tokens.COMMA) { read(); continue; } break; } Expression[] array = new Expression[list.size()]; list.toArray(array); Expression e = new Expression(OpTypes.VALUELIST, array); for (int i = 0; i < array.length; i++) { if (array[i].getType() != OpTypes.ROW) { array[i] = new Expression(OpTypes.ROW, new Expression[]{ array[i] }); } Expression[] args = array[i].nodes; if (args.length != degree) { // SQL error message throw unexpectedToken(); } for (int j = 0; j < degree; j++) { if (args[j].getType() == OpTypes.ROW) { // SQL error message throw unexpectedToken(); } } } return e; } private ExpressionLogical XreadLikePredicateRightPart(Expression a) { read(); Expression b = XreadStringValueExpression(); Expression escape = null; if (token.tokenString.equals(Tokens.T_ESCAPE)) { read(); escape = XreadStringValueExpression(); } return new ExpressionLike(a, b, escape, isCheckOrTriggerCondition); } private ExpressionLogical XreadMatchPredicateRightPart(Expression a) { boolean isUnique = false; int matchType = OpTypes.MATCH_SIMPLE; read(); if (token.tokenType == Tokens.UNIQUE) { read(); isUnique = true; } switch (token.tokenType) { default : matchType = isUnique ? OpTypes.MATCH_UNIQUE_SIMPLE : OpTypes.MATCH_SIMPLE; break; case Tokens.SIMPLE : read(); matchType = isUnique ? OpTypes.MATCH_UNIQUE_SIMPLE : OpTypes.MATCH_SIMPLE; break; case Tokens.PARTIAL : read(); matchType = isUnique ? OpTypes.MATCH_UNIQUE_PARTIAL : OpTypes.MATCH_PARTIAL; break; case Tokens.FULL : read(); matchType = isUnique ? OpTypes.MATCH_UNIQUE_FULL : OpTypes.MATCH_FULL; break; } int mode = isUnique ? OpTypes.MATCH_SIMPLE : OpTypes.IN; Expression s = XreadTableSubquery(mode); return new ExpressionLogical(matchType, a, s); }
OVERLAPS does not require PERIOD, others do. CONTAINS can have single value right side
/** * OVERLAPS does not require PERIOD, others do. * CONTAINS can have single value right side */
private ExpressionLogical XreadPeriodPredicateRightPart(int opType, Expression left) { boolean isLeftRow = false; switch (left.getType()) { case OpTypes.COLUMN : left = new ExpressionPeriod((ExpressionColumn) left); break; case OpTypes.PERIOD : break; case OpTypes.ROW : if (left.nodes.length != 2) { throw Error.error(ErrorCode.X_42564); } isLeftRow = true; break; default : throw Error.error(ErrorCode.X_42564); } read(); boolean period = false; if (token.tokenType == Tokens.PERIOD) { if (isLeftRow) { throw unexpectedToken(); } read(); period = true; if (token.tokenType != Tokens.OPENBRACKET) { throw unexpectedTokenRequire(Tokens.T_OPENBRACKET); } } Expression right = XreadRowValuePredicand(); switch (right.getType()) { case OpTypes.COLUMN : if (period) { throw Error.error(ErrorCode.X_42564); } right = new ExpressionPeriod((ExpressionColumn) right); break; case OpTypes.ROW : if (right.nodes.length == 2) { if (period) { right = new ExpressionPeriod(right); } else { if (opType != OpTypes.RANGE_OVERLAPS) { throw Error.error(ErrorCode.X_42564); } return new ExpressionLogical(OpTypes.OVERLAPS, left, right); } break; } throw Error.error(ErrorCode.X_42564); default : if (opType != OpTypes.RANGE_CONTAINS) { throw Error.error(ErrorCode.X_42564); } if (period) { throw Error.error(ErrorCode.X_42564); } break; } return new ExpressionPeriodOp(opType, left, right); } Expression XreadRowValueExpression() { Expression e = XreadExplicitRowValueConstructorOrNull(); if (e != null) { return e; } return XreadRowValueSpecialCase(); } Expression XreadTableRowValueConstructor() { Expression e = XreadExplicitRowValueConstructorOrNull(); if (e != null) { return e; } return XreadRowValueSpecialCase(); } // union of <row value expression> | // <boolean predicand> | <non parenthesized value expression primary> | // translated to <explicit row value constructor> // <value expression primary> | <non parenthesized value expression primary> | Expression XreadRowValuePredicand() { return XreadRowOrCommonValueExpression(); } Expression XreadRowValueSpecialCase() { Expression e = XreadSimpleValueExpressionPrimary(); if (e != null) { e = XreadArrayElementReference(e); } return e; } // <row value constructor> // ISSUE - XreadCommonValueExpression and XreadBooleanValueExpression should merge Expression XreadRowValueConstructor() { Expression e; e = XreadExplicitRowValueConstructorOrNull(); if (e != null) { return e; } e = XreadRowOrCommonValueExpression(); if (e != null) { return e; } return XreadBooleanValueExpression(); } // returns null // must be called in conjunction with <parenthesized .. Expression XreadExplicitRowValueConstructorOrNull() { Expression e; switch (token.tokenType) { case Tokens.OPENBRACKET : { read(); int position = getPosition(); readOpenBrackets(); switch (token.tokenType) { case Tokens.TABLE : case Tokens.VALUES : case Tokens.SELECT : rewind(position); TableDerived td = XreadSubqueryTableBody(OpTypes.ROW_SUBQUERY); readThis(Tokens.CLOSEBRACKET); return new Expression(OpTypes.ROW_SUBQUERY, td); default : rewind(position); e = XreadRowElementList(true); readThis(Tokens.CLOSEBRACKET); return e; } } case Tokens.ROW : { read(); readThis(Tokens.OPENBRACKET); e = XreadRowElementList(false); readThis(Tokens.CLOSEBRACKET); return e; } } return null; } Expression XreadRowElementList(boolean multiple) { Expression e; HsqlArrayList list = new HsqlArrayList(); while (true) { e = XreadValueExpression(); list.add(e); if (token.tokenType == Tokens.COMMA) { read(); continue; } if (multiple && list.size() == 1) { return e; } break; } Expression[] array = new Expression[list.size()]; list.toArray(array); return new Expression(OpTypes.ROW, array); } Expression XreadCurrentCollationSpec() { throw Error.error(ErrorCode.X_0A000); } Expression XreadTableSubquery(int mode) { readThis(Tokens.OPENBRACKET); TableDerived td = XreadSubqueryTableBody(mode); readThis(Tokens.CLOSEBRACKET); return new Expression(OpTypes.TABLE_SUBQUERY, td); } Table XreadTableSubqueryOrNull(boolean parens) { boolean joinedTable = false; int position; position = getPosition(); readThis(Tokens.OPENBRACKET); switch (token.tokenType) { case Tokens.TABLE : case Tokens.VALUES : case Tokens.SELECT : case Tokens.WITH : break; case Tokens.OPENBRACKET : if (parens) { break; } // fall through default : joinedTable = true; } if (joinedTable) { rewind(position); return null; } else { TableDerived td = XreadSubqueryTableBody(OpTypes.TABLE_SUBQUERY); readThis(Tokens.CLOSEBRACKET); return td; } } TableDerived XreadJoinedTableAsSubqueryOrNull() { int position = getPosition(); readThis(Tokens.OPENBRACKET); compileContext.incrementDepth(); QuerySpecification qs = XreadJoinedTableAsView(); qs.resolveReferences(session, compileContext.getOuterRanges()); if (qs.rangeVariables.length < 2) { compileContext.decrementDepth(); rewind(position); return null; } qs.resolveTypesPartOne(session); qs.resolveTypesPartTwo(session); TableDerived td = newSubQueryTable(qs, OpTypes.TABLE_SUBQUERY); readThis(Tokens.CLOSEBRACKET); td.setSQL(getLastPart(position)); td.prepareTable(session); compileContext.decrementDepth(); return td; } QuerySpecification XreadJoinedTableAsView() { QuerySpecification select = new QuerySpecification(compileContext); Expression e = new ExpressionColumn(OpTypes.MULTICOLUMN); select.addSelectColumnExpression(e); XreadTableReference(select); return select; } TableDerived XreadTableNamedSubqueryBody(HsqlName name, HsqlName[] columnNames, int type) { TableDerived td; int position = getPosition(); int depth = compileContext.getDepth(); switch (type) { case OpTypes.RECURSIVE_SUBQUERY : { try { td = XreadRecursiveSubqueryBody(name, columnNames); break; } catch (HsqlException e) { rewind(position); compileContext.decrementDepth(depth); } } // fall through case OpTypes.TABLE_SUBQUERY : { try { td = XreadSubqueryTableBody(name, type); if (td.queryExpression != null) { td.canRecompile = true; td.queryExpression.resolve( session, compileContext.getOuterRanges(), null); } td.prepareTable(session, columnNames); break; } catch (HsqlException e) { if (database.sqlSyntaxDb2 || database.sqlSyntaxOra) { rewind(position); compileContext.decrementDepth(depth); td = XreadRecursiveSubqueryBody(name, columnNames); break; } throw e; } } default : throw unexpectedToken(); } return td; } TableDerived XreadRecursiveSubqueryBody(HsqlName name, HsqlName[] columnNames) { int position = getPosition(); compileContext.incrementDepth(); compileContext.incrementDepth(); QuerySpecification leftQuerySpecification = XreadSimpleTable(); leftQuerySpecification.resolveReferences(session, compileContext.getOuterRanges()); leftQuerySpecification.resolve(session); TableDerived td = newSubQueryTable(name, leftQuerySpecification, OpTypes.TABLE_SUBQUERY); compileContext.decrementDepth(); td.prepareTable(session, columnNames); compileContext.registerSubquery(name.name); compileContext.registerSubquery(name.name, td); checkIsThis(Tokens.UNION); int unionType = XreadUnionType(); if (database.sqlSyntaxDb2 || database.sqlSyntaxOra || database.sqlSyntaxMss || database.sqlSyntaxPgs) { if (unionType == QueryExpression.UNION_ALL) { unionType = QueryExpression.UNION; } } QuerySpecification rightQuerySpecification = XreadSimpleTable(); QueryExpression queryExpression = new QueryExpression(compileContext, leftQuerySpecification); rightQuerySpecification.isBaseMergeable = false; rightQuerySpecification.resolveReferences(session, compileContext.getOuterRanges()); queryExpression.addUnion(rightQuerySpecification, unionType); queryExpression.isRecursive = true; queryExpression.recursiveTable = td; queryExpression.resolve(session); TableDerived maintd = newSubQueryTable(name, queryExpression, OpTypes.TABLE_SUBQUERY); maintd.prepareTable(session, columnNames); maintd.setSQL(getLastPart(position)); compileContext.decrementDepth(); return maintd; } TableDerived newSubQueryTable(Expression e, int opType) { HsqlName name = database.nameManager.getSubqueryTableName(); TableDerived td = new TableDerived(database, name, TableBase.SYSTEM_SUBQUERY, null, e, opType, compileContext.getDepth()); return td; } TableDerived newSubQueryTable(QueryExpression qe, int opType) { return newSubQueryTable(null, qe, opType); } TableDerived newSubQueryTable(HsqlName name, QueryExpression qe, int opType) { if (name == null) { name = database.nameManager.getSubqueryTableName(); } TableDerived td = new TableDerived(database, name, TableBase.SYSTEM_SUBQUERY, qe, null, opType, compileContext.getDepth()); return td; } TableDerived XreadSubqueryTableBody(int type) { return XreadSubqueryTableBody(null, type); } TableDerived XreadSubqueryTableBody(HsqlName name, int type) { int position = getPosition(); compileContext.incrementDepth(); QueryExpression queryExpression = XreadQueryExpression(); TableDerived td = null; if (type == OpTypes.EXISTS) { queryExpression.setAsExists(); } if (queryExpression.isValueList) { td = ((QuerySpecification) queryExpression).getValueListTable(); } if (td == null) { td = newSubQueryTable(name, queryExpression, type); } td.setSQL(getLastPart(position)); compileContext.decrementDepth(); return td; } TableDerived XreadViewSubqueryTable(View view, boolean resolve) { compileContext.incrementDepth(); QueryExpression queryExpression; try { queryExpression = XreadQueryExpression(); } catch (HsqlException e) { queryExpression = XreadJoinedTableAsView(); } queryExpression.setView(view); queryExpression.resolveReferences(session, RangeGroup.emptyArray); queryExpression.resolveTypesPartOne(session); queryExpression.resolveTypesPartTwo(session); if (resolve) { queryExpression.resolveTypesPartThree(session); } TableDerived td = new TableDerived(database, view.getName(), TableBase.VIEW_TABLE, queryExpression, null, OpTypes.NONE, compileContext.getDepth()); td.view = view; td.columnList = view.columnList; td.columnCount = view.columnList.size(); td.createPrimaryKey(); td.triggerList = view.triggerList; td.triggerLists = view.triggerLists; compileContext.decrementDepth(); return td; } Expression XreadContextuallyTypedTable(int degree) { Expression e = readRow(); Expression[] list = e.nodes; boolean isTable = false; if (degree == 1) { if (e.getType() == OpTypes.ROW) { e.opType = OpTypes.VALUELIST; for (int i = 0; i < list.length; i++) { if (list[i].getType() != OpTypes.ROW) { list[i] = new Expression(OpTypes.ROW, new Expression[]{ list[i] }); } else if (list[i].nodes.length != degree) { throw Error.error(ErrorCode.X_42564); } } return e; } else { e = new Expression(OpTypes.ROW, new Expression[]{ e }); e = new Expression(OpTypes.VALUELIST, new Expression[]{ e }); return e; } } if (e.getType() != OpTypes.ROW) { throw Error.error(ErrorCode.X_42564); } for (int i = 0; i < list.length; i++) { if (list[i].getType() == OpTypes.ROW) { isTable = true; break; } } if (isTable) { e.opType = OpTypes.VALUELIST; for (int i = 0; i < list.length; i++) { if (list[i].getType() != OpTypes.ROW) { throw Error.error(ErrorCode.X_42564); } Expression[] args = list[i].nodes; if (args.length != degree) { throw Error.error(ErrorCode.X_42564); } for (int j = 0; j < degree; j++) { if (args[j].getType() == OpTypes.ROW) { throw Error.error(ErrorCode.X_42564); } } } } else { if (list.length != degree) { throw Error.error(ErrorCode.X_42564); } e = new Expression(OpTypes.VALUELIST, new Expression[]{ e }); } return e; } Expression XreadInValueListConstructor(int degree) { int position = getPosition(); compileContext.incrementDepth(); Expression e = XreadInValueList(degree); TableDerived td = newSubQueryTable(e, OpTypes.IN); td.setSQL(getLastPart(position)); e.table = td; compileContext.decrementDepth(); return e; } private TableDerived XreadRowValueExpressionList() { compileContext.incrementDepth(); Expression e = XreadRowValueExpressionListBody(); TableDerived td = prepareSubqueryTable(e, null); compileContext.decrementDepth(); return td; } private TableDerived prepareSubqueryTable(Expression e, HsqlName[] colNames) { HsqlList unresolved = e.resolveColumnReferences(session, RangeGroup.emptyGroup, compileContext.getOuterRanges(), null); ExpressionColumn.checkColumnsResolved(unresolved); e.resolveTypes(session, null); e.prepareTable(session, null, e.nodes[0].nodes.length); TableDerived td = newSubQueryTable(e, OpTypes.VALUELIST); td.prepareTable(session, colNames); return td; } Expression XreadRowValueExpressionListBody() { Expression r = null; while (true) { int brackets = readOpenBrackets(); Expression e = readRow(); readCloseBrackets(brackets); if (r == null) { r = new Expression(OpTypes.ROW, new Expression[]{ e }); } else { r.nodes = (Expression[]) ArrayUtil.resizeArray(r.nodes, r.nodes.length + 1); r.nodes[r.nodes.length - 1] = e; } if (token.tokenType != Tokens.COMMA) { break; } read(); } Expression[] list = r.nodes; int degree = 1; if (list[0].getType() == OpTypes.ROW) { degree = list[0].nodes.length; } r.opType = OpTypes.VALUELIST; for (int i = 0; i < list.length; i++) { if (list[i].getType() == OpTypes.ROW) { if (list[i].nodes.length != degree) { throw Error.error(ErrorCode.X_42564); } } else { if (degree != 1) { throw Error.error(ErrorCode.X_42564); } list[i] = new Expression(OpTypes.ROW, new Expression[]{ list[i] }); } } return r; } Expression XreadTargetSpecification(RangeVariable[] rangeVars, LongDeque colIndexList) { ColumnSchema column = null; int index = -1; checkIsIdentifier(); if (token.namePrePrePrefix != null) { checkValidCatalogName(token.namePrePrePrefix); } for (int i = 0; i < rangeVars.length; i++) { if (rangeVars[i] == null) { continue; } index = rangeVars[i].findColumn(token.namePrePrefix, token.namePrefix, token.tokenString); if (index > -1) { column = rangeVars[i].getColumn(index); read(); break; } } if (column == null) { throw Error.error(ErrorCode.X_42501, token.tokenString); } colIndexList.add(index); if (token.tokenType == Tokens.LEFTBRACKET) { if (!column.getDataType().isArrayType()) { throw unexpectedToken(); } read(); Expression e = XreadNumericValueExpression(); if (e == null) { throw Error.error(ErrorCode.X_42501, token.tokenString); } e = new ExpressionAccessor(column.getAccessor(), e); readThis(Tokens.RIGHTBRACKET); return e; } return column.getAccessor(); } Expression XreadCollectionDerivedTable(int type) { boolean ordinality = false; int position = getPosition(); readThis(Tokens.UNNEST); readThis(Tokens.OPENBRACKET); compileContext.incrementDepth(); HsqlArrayList list = new HsqlArrayList(); while (true) { Expression e = XreadValueExpression(); list.add(e); if (token.tokenType == Tokens.COMMA) { read(); } else { break; } } Expression[] array = new Expression[list.size()]; list.toArray(array); readThis(Tokens.CLOSEBRACKET); if (token.tokenType == Tokens.WITH) { read(); readThis(Tokens.ORDINALITY); ordinality = true; } Expression e = new ExpressionTable(array, ordinality); TableDerived td = newSubQueryTable(e, type); td.setSQL(getLastPart(position)); compileContext.decrementDepth(); return e; } Expression XreadTableFunctionDerivedTable() { int position = getPosition(); readThis(Tokens.TABLE); readThis(Tokens.OPENBRACKET); compileContext.incrementDepth(); Expression e = XreadValueExpression(); if (e.getType() != OpTypes.FUNCTION && e.getType() != OpTypes.SQL_FUNCTION) { compileContext.decrementDepth(); throw unexpectedToken(Tokens.T_TABLE); } readThis(Tokens.CLOSEBRACKET); e = new ExpressionTable(new Expression[]{ e }, false); TableDerived td = newSubQueryTable(e, OpTypes.TABLE_SUBQUERY); td.setSQL(getLastPart(position)); compileContext.decrementDepth(); return e; } Expression XreadLateralDerivedTable() { readThis(Tokens.LATERAL); readThis(Tokens.OPENBRACKET); TableDerived td = XreadSubqueryTableBody(OpTypes.TABLE_SUBQUERY); readThis(Tokens.CLOSEBRACKET); return new Expression(OpTypes.TABLE_SUBQUERY, td); } Expression XreadArrayConstructor() { readThis(Tokens.OPENBRACKET); TableDerived td = XreadSubqueryTableBody(OpTypes.TABLE_SUBQUERY); readThis(Tokens.CLOSEBRACKET); return new Expression(OpTypes.ARRAY_SUBQUERY, td); } // Additional Common Elements Collation readCollateClauseOrNull() { if (token.tokenType == Tokens.COLLATE) { read(); Collation collation = database.schemaManager.getCollation(session, token.tokenString, token.namePrefix); return collation; } return null; } Expression XreadArrayElementReference(Expression e) { if (token.tokenType == Tokens.LEFTBRACKET) { read(); Expression e1 = XreadNumericValueExpression(); readThis(Tokens.RIGHTBRACKET); e = new ExpressionAccessor(e, e1); } return e; } Expression readRow() { Expression r = null; while (true) { Expression e = XreadValueExpressionWithContext(); if (r == null) { r = e; } else if (r.getType() == OpTypes.ROW) { if (e.getType() == OpTypes.ROW && r.nodes[0].getType() != OpTypes.ROW) { r = new Expression(OpTypes.ROW, new Expression[] { r, e }); } else { r.nodes = (Expression[]) ArrayUtil.resizeArray(r.nodes, r.nodes.length + 1); r.nodes[r.nodes.length - 1] = e; } } else { r = new Expression(OpTypes.ROW, new Expression[] { r, e }); } if (token.tokenType != Tokens.COMMA) { break; } read(); } return r; } Expression readCaseExpression() { Expression predicand = null; read(); if (token.tokenType != Tokens.WHEN) { predicand = XreadRowValuePredicand(); } return readCaseWhen(predicand); }
Reads part of a CASE .. WHEN expression
/** * Reads part of a CASE .. WHEN expression */
private Expression readCaseWhen(final Expression l) { readThis(Tokens.WHEN); Expression condition = null; if (l == null) { condition = XreadBooleanValueExpression(); } else { while (true) { Expression newCondition = XreadPredicateRightPart(l); if (l == newCondition) { newCondition = new ExpressionLogical(l, XreadRowValuePredicand()); } if (condition == null) { condition = newCondition; } else { condition = new ExpressionLogical(OpTypes.OR, condition, newCondition); } if (token.tokenType == Tokens.COMMA) { read(); } else { break; } } } readThis(Tokens.THEN); Expression current = XreadValueExpression(); Expression elseExpr = null; if (token.tokenType == Tokens.WHEN) { elseExpr = readCaseWhen(l); } else if (token.tokenType == Tokens.ELSE) { read(); elseExpr = XreadValueExpression(); readThis(Tokens.END); readIfThis(Tokens.CASE); } else { elseExpr = new ExpressionValue((Object) null, (Type) null); readThis(Tokens.END); readIfThis(Tokens.CASE); } Expression alt = new ExpressionOp(OpTypes.ALTERNATIVE, current, elseExpr); Expression casewhen = new ExpressionOp(OpTypes.CASEWHEN, condition, alt); return casewhen; }
reads a CASEWHEN expression
/** * reads a CASEWHEN expression */
private Expression readCaseWhenExpressionOrNull() { Expression l = null; int position = getPosition(); if (token.tokenType == Tokens.IF) { if (database.sqlSyntaxMys || database.sqlSyntaxMss) {} else { return null; } } read(); if (!readIfThis(Tokens.OPENBRACKET)) { rewind(position); return null; } l = XreadBooleanValueExpression(); readThis(Tokens.COMMA); Expression then = XreadValueExpression(); readThis(Tokens.COMMA); Expression thenelse = new ExpressionOp(OpTypes.ALTERNATIVE, then, XreadValueExpression()); l = new ExpressionOp(OpTypes.CASEWHEN, l, thenelse); readThis(Tokens.CLOSEBRACKET); return l; }
Reads a CAST expression
/** * Reads a CAST expression */
private Expression readCastExpression() { Expression e; Type typeObject; read(); readThis(Tokens.OPENBRACKET); e = XreadValueExpression(); readThis(Tokens.AS); typeObject = readTypeDefinition(false, true); if (e.isUnresolvedParam()) { e.setDataType(session, typeObject); } else { e = new ExpressionOp(e, typeObject); } readThis(Tokens.CLOSEBRACKET); return e; } private Expression readConvertExpressionOrNull() { Expression e; Expression mode = null; Type typeObject; int position = getPosition(); read(); if (!readIfThis(Tokens.OPENBRACKET)) { rewind(position); return null; } if (database.sqlSyntaxMss) { typeObject = readTypeDefinition(false, true); readThis(Tokens.COMMA); e = XreadValueExpression(); if (readIfThis(Tokens.COMMA)) { mode = this.XreadSimpleValueSpecificationOrNull(); } } else { e = XreadValueExpression(); readThis(Tokens.COMMA); typeObject = Type.getTypeForJDBCConvertToken(token.tokenType); if (typeObject == null) { typeObject = readTypeDefinition(false, true); } else { read(); } } if (e.isUnresolvedParam() && mode == null) { e.setDataType(session, typeObject); } else { e = new ExpressionOp(e, typeObject, mode); } readThis(Tokens.CLOSEBRACKET); return e; }
reads a Column or Function expression
/** * reads a Column or Function expression */
private Expression readColumnOrFunctionExpression() { String name = token.tokenString; boolean isSimpleQuoted = isDelimitedSimpleName(); Token recordedToken = getRecordedToken(); checkIsIdentifier(); if (isUndelimitedSimpleName()) { Expression e = readFunction(); if (e != null) { return e; } } read(); if (token.tokenType != Tokens.OPENBRACKET) { checkValidCatalogName(recordedToken.namePrePrePrefix); Expression column = new ExpressionColumn(recordedToken.namePrePrefix, recordedToken.namePrefix, name); return column; } RoutineSchema routineSchema = (RoutineSchema) database.schemaManager.findSchemaObject(session, name, recordedToken.namePrefix, recordedToken.namePrePrefix, SchemaObject.FUNCTION); if (routineSchema == null && recordedToken.namePrefix == null && !isViewDefinition) { String schema = session.getSchemaName(null); ReferenceObject synonym = database.schemaManager.findSynonym(recordedToken.tokenString, schema, SchemaObject.ROUTINE); if (synonym != null) { HsqlName synonymName = synonym.getTarget(); routineSchema = (RoutineSchema) database.schemaManager.findSchemaObject( synonymName.name, synonymName.schema.name, SchemaObject.ROUTINE); } } if (routineSchema == null && isSimpleQuoted) { HsqlName schema = database.schemaManager.getDefaultSchemaHsqlName(); routineSchema = (RoutineSchema) database.schemaManager.findSchemaObject(name, schema.name, SchemaObject.FUNCTION); if (routineSchema == null) { Routine.createRoutines(session, schema, name); routineSchema = (RoutineSchema) database.schemaManager.findSchemaObject( name, schema.name, SchemaObject.FUNCTION); } } if (routineSchema == null) { if (lastError != null) { throw lastError; } throw Error.error(ErrorCode.X_42501, name); } HsqlArrayList list = new HsqlArrayList(); readThis(Tokens.OPENBRACKET); if (token.tokenType == Tokens.CLOSEBRACKET) { read(); } else { while (true) { Expression e = XreadValueExpression(); list.add(e); if (token.tokenType == Tokens.COMMA) { read(); } else { readThis(Tokens.CLOSEBRACKET); break; } } } FunctionSQLInvoked function = new FunctionSQLInvoked(routineSchema); Expression[] arguments = new Expression[list.size()]; list.toArray(arguments); function.setArguments(arguments); compileContext.addFunctionCall(function); recordedToken.setExpression(routineSchema); return function; } Expression readFunction() { FunctionSQL function = FunctionCustom.newCustomFunction(session, token.tokenString, token.tokenType); if (function != null) { int pos = getPosition(); try { Expression e = readSQLFunction(function); if (e != null) { return e; } } catch (HsqlException ex) { ex.setLevel(compileContext.subqueryDepth); if (lastError == null || lastError.getLevel() < ex.getLevel()) { lastError = ex; } rewind(pos); } } else if (isReservedKey()) { function = FunctionSQL.newSQLFunction(token.tokenString, compileContext); if (function != null) { Expression e = readSQLFunction(function); if (e != null) { return e; } } } return null; } Expression readCollection(int type) { read(); if (token.tokenType == Tokens.OPENBRACKET) { return XreadArrayConstructor(); } else { readThis(Tokens.LEFTBRACKET); HsqlArrayList list = new HsqlArrayList(); for (int i = 0; ; i++) { if (token.tokenType == Tokens.RIGHTBRACKET) { read(); break; } if (i > 0) { readThis(Tokens.COMMA); } Expression e = XreadValueExpression(); list.add(e); } Expression[] array = new Expression[list.size()]; list.toArray(array); return new Expression(OpTypes.ARRAY, array); } } private Expression readDecodeExpressionOrNull() { int position = getPosition(); read(); if (!readIfThis(Tokens.OPENBRACKET)) { rewind(position); return null; } Expression casewhen = null; Expression alternative = null; Expression main = XreadValueExpression(); readThis(Tokens.COMMA); do { Expression v = XreadValueExpression(); if (token.tokenType == Tokens.COMMA) { readThis(Tokens.COMMA); } else { if (alternative == null) { throw unexpectedToken(); } alternative.setRightNode(v); break; } Expression l = new ExpressionLogical(OpTypes.NOT_DISTINCT, main, v); Expression r = XreadValueExpression(); Expression a = new ExpressionOp(OpTypes.ALTERNATIVE, r, null); Expression c = new ExpressionOp(OpTypes.CASEWHEN, l, a); if (casewhen == null) { casewhen = c; } else { alternative.setRightNode(c); } alternative = a; if (token.tokenType == Tokens.COMMA) { readThis(Tokens.COMMA); } else { alternative.setRightNode(new ExpressionValue(null, null)); break; } } while (true); readThis(Tokens.CLOSEBRACKET); return casewhen; } private Expression readConcatExpressionOrNull() { Expression root; Expression r; // turn into a concatenation int position = getPosition(); read(); if (!readIfThis(Tokens.OPENBRACKET)) { rewind(position); return null; } root = XreadValueExpression(); readThis(Tokens.COMMA); do { r = XreadValueExpression(); root = new ExpressionArithmetic(OpTypes.CONCAT, root, r); if (token.tokenType == Tokens.COMMA) { readThis(Tokens.COMMA); } else if (token.tokenType == Tokens.CLOSEBRACKET) { readThis(Tokens.CLOSEBRACKET); break; } } while (true); return root; } private Expression readConcatSeparatorExpressionOrNull() { HsqlArrayList array = new HsqlArrayList(); int position = getPosition(); read(); if (!readIfThis(Tokens.OPENBRACKET)) { rewind(position); return null; } Expression e = XreadValueExpression(); array.add(e); readThis(Tokens.COMMA); e = XreadValueExpression(); array.add(e); readThis(Tokens.COMMA); do { e = XreadValueExpression(); array.add(e); if (token.tokenType == Tokens.COMMA) { readThis(Tokens.COMMA); } else if (token.tokenType == Tokens.CLOSEBRACKET) { readThis(Tokens.CLOSEBRACKET); break; } } while (true); Expression[] expressions = new Expression[array.size()]; array.toArray(expressions); return new ExpressionOp(OpTypes.CONCAT_WS, expressions); } private Expression readLeastExpressionOrNull() { int position = getPosition(); read(); if (!readIfThis(Tokens.OPENBRACKET)) { rewind(position); return null; } Expression casewhen = null; do { casewhen = readValue(casewhen, OpTypes.SMALLER); if (token.tokenType == Tokens.COMMA) { readThis(Tokens.COMMA); } else { break; } } while (true); readThis(Tokens.CLOSEBRACKET); return casewhen; } private Expression readGreatestExpressionOrNull() { int position = getPosition(); read(); if (!readIfThis(Tokens.OPENBRACKET)) { rewind(position); return null; } Expression casewhen = null; do { casewhen = readValue(casewhen, OpTypes.GREATER); if (token.tokenType == Tokens.COMMA) { readThis(Tokens.COMMA); } else { break; } } while (true); readThis(Tokens.CLOSEBRACKET); return casewhen; } private Expression readValue(Expression e, int opType) { Expression r = XreadValueExpression(); if (e == null) { return r; } Expression l = new ExpressionLogical(opType, e, r); Expression a = new ExpressionOp(OpTypes.ALTERNATIVE, e, r); return new ExpressionOp(OpTypes.CASEWHEN, l, a); }
Reads a NULLIF expression
/** * Reads a NULLIF expression */
private Expression readNullIfExpression() { read(); readThis(Tokens.OPENBRACKET); Expression c = XreadValueExpression(); readThis(Tokens.COMMA); Expression alternative = new ExpressionOp(OpTypes.ALTERNATIVE, new ExpressionValue((Object) null, (Type) null), c); c = new ExpressionLogical(c, XreadValueExpression()); c = new ExpressionOp(OpTypes.CASEWHEN, c, alternative); readThis(Tokens.CLOSEBRACKET); return c; }
Reads a ISNULL or ISNULL of NVL expression
/** * Reads a ISNULL or ISNULL of NVL expression */
private Expression readIfNullExpressionOrNull() { int position = getPosition(); read(); if (!readIfThis(Tokens.OPENBRACKET)) { rewind(position); return null; } Expression c = XreadValueExpression(); readThis(Tokens.COMMA); Expression e = XreadValueExpression(); Expression condition = new ExpressionLogical(OpTypes.IS_NULL, c); Expression alt = new ExpressionOp(OpTypes.ALTERNATIVE, e, c); c = new ExpressionOp(OpTypes.CASEWHEN, condition, alt); c.setSubType(OpTypes.CAST); alt.setSubType(OpTypes.CAST); readThis(Tokens.CLOSEBRACKET); return c; }
Reads a NVL2 expression
/** * Reads a NVL2 expression */
private Expression readIfNull2ExpressionOrNull() { int position = getPosition(); read(); if (!readIfThis(Tokens.OPENBRACKET)) { rewind(position); return null; } Expression c = XreadValueExpression(); readThis(Tokens.COMMA); Expression e1 = XreadValueExpression(); readThis(Tokens.COMMA); Expression e2 = XreadValueExpression(); Expression condition = new ExpressionLogical(OpTypes.IS_NULL, c); Expression alt = new ExpressionOp(OpTypes.ALTERNATIVE, e2, e1); c = new ExpressionOp(OpTypes.CASEWHEN, condition, alt); c.setSubType(OpTypes.CAST); alt.setSubType(OpTypes.CAST); readThis(Tokens.CLOSEBRACKET); return c; }
Reads a COALESE expression
/** * Reads a COALESE expression */
private Expression readCoalesceExpression() { Expression c = null; read(); readThis(Tokens.OPENBRACKET); Expression leaf = null; while (true) { Expression current = XreadValueExpression(); if (leaf != null && token.tokenType == Tokens.CLOSEBRACKET) { readThis(Tokens.CLOSEBRACKET); leaf.setLeftNode(current); break; } Expression expressionNull = new ExpressionValue((Object) null, (Type) null); Expression condition = new ExpressionLogical(OpTypes.IS_NULL, current); Expression alt = new ExpressionOp(OpTypes.ALTERNATIVE, expressionNull, current); Expression casewhen = new ExpressionOp(OpTypes.CASEWHEN, condition, alt); if (session.database.sqlSyntaxMys) { alt.setSubType(OpTypes.CAST); casewhen.setSubType(OpTypes.CAST); } if (c == null) { c = casewhen; } else { leaf.setLeftNode(casewhen); } leaf = alt; readThis(Tokens.COMMA); } return c; } Expression readSQLFunction(FunctionSQL function) { int position = getPosition(); read(); short[] parseList = function.parseList; if (parseList.length == 0) { return function; } HsqlArrayList exprList = new HsqlArrayList(); boolean isOpenBracket = token.tokenType == Tokens.OPENBRACKET; if (!isOpenBracket) { if (parseList[0] == Tokens.X_OPTION) { return function; } else { rewind(position); return null; } } try { readExpression(exprList, parseList, 0, parseList.length, false); lastError = null; } catch (HsqlException e) { if (function.parseListAlt == null) { throw e; } rewind(position); read(); parseList = function.parseListAlt; exprList = new HsqlArrayList(); readExpression(exprList, parseList, 0, parseList.length, false); lastError = null; } Expression[] expr = new Expression[exprList.size()]; exprList.toArray(expr); function.setArguments(expr); return function.getFunctionExpression(); } void readExpression(HsqlArrayList exprList, short[] parseList, int start, int count, boolean isOption) { for (int i = start; i < start + count; i++) { int exprType = parseList[i]; switch (exprType) { case Tokens.QUESTION : { Expression e = null; e = XreadAllTypesCommonValueExpression(false); exprList.add(e); continue; } case Tokens.X_TOKEN : { if (super.isUndelimitedSimpleName()) { Expression e = new ExpressionValue(token.tokenString, Type.SQL_VARCHAR); read(); exprList.add(e); continue; } throw unexpectedToken(); } case Tokens.X_POS_INTEGER : { Expression e = null; Integer value = readIntegerObject(); if (value.intValue() < 0) { throw Error.error(ErrorCode.X_42592); } e = new ExpressionValue(value, Type.SQL_INTEGER); exprList.add(e); continue; } case Tokens.X_OPTION : { i++; int expressionCount = exprList.size(); int position = getPosition(); int elementCount = parseList[i++]; int initialExprIndex = exprList.size(); try { readExpression(exprList, parseList, i, elementCount, true); } catch (HsqlException ex) { ex.setLevel(compileContext.subqueryDepth); if (lastError == null || lastError.getLevel() < ex.getLevel()) { lastError = ex; } rewind(position); exprList.setSize(expressionCount); for (int j = i; j < i + elementCount; j++) { if (parseList[j] == Tokens.QUESTION || parseList[j] == Tokens.X_KEYSET || parseList[j] == Tokens.X_POS_INTEGER) { exprList.add(null); } } i += elementCount - 1; continue; } if (initialExprIndex == exprList.size()) { if (parseList[i] != Tokens.OPENBRACKET) { exprList.add(null); } } i += elementCount - 1; continue; } case Tokens.X_REPEAT : { i++; int elementCount = parseList[i++]; int parseIndex = i; while (true) { int initialExprIndex = exprList.size(); readExpression(exprList, parseList, parseIndex, elementCount, true); if (exprList.size() == initialExprIndex) { break; } } i += elementCount - 1; continue; } case Tokens.X_KEYSET : { int elementCount = parseList[++i]; Expression e = null; if (ArrayUtil.find(parseList, token.tokenType, i + 1, elementCount) == -1) { if (!isOption) { throw unexpectedToken(); } } else { e = new ExpressionValue( ValuePool.getInt(token.tokenType), Type.SQL_INTEGER); read(); } exprList.add(e); i += elementCount; continue; } case Tokens.OPENBRACKET : case Tokens.CLOSEBRACKET : case Tokens.COMMA : default : if (token.tokenType != exprType) { throw unexpectedToken(); } read(); } } } private Expression readSequenceExpressionOrNull(int opType) { int position = getPosition(); switch (opType) { case OpTypes.SEQUENCE : if (token.tokenType == Tokens.NEXT) { read(); if (token.tokenType != Tokens.VALUE) { rewind(position); return null; } readThis(Tokens.VALUE); } else if (database.sqlSyntaxDb2 && token.tokenType == Tokens.NEXTVAL) { read(); } else if (database.sqlSyntaxDb2 && token.tokenType == Tokens.PREVVAL) { read(); } else { rewind(position); return null; } break; case OpTypes.SEQUENCE_CURRENT : read(); readThis(Tokens.VALUE); break; default : } readThis(Tokens.FOR); checkIsSchemaObjectName(); NumberSequence sequence = database.schemaManager.findSequence(session, token.tokenString, token.namePrefix); if (sequence == null) { throw Error.error(ErrorCode.X_42501, token.tokenString); } Token recordedToken = getRecordedToken(); read(); Expression e = new ExpressionColumn(sequence, opType); recordedToken.setExpression(sequence); compileContext.addSequence(sequence); return e; } SimpleName readSimpleName() { checkIsSimpleName(); SimpleName name = HsqlNameManager.getSimpleName(token.tokenString, isDelimitedIdentifier()); read(); return name; } HsqlName readNewSchemaName() { HsqlName name = readNewSchemaObjectName(SchemaObject.SCHEMA, false); SqlInvariants.checkSchemaNameNotSystem(name.name); return name; } HsqlName readNewSchemaObjectName(int type, boolean checkSchema) { checkIsSchemaObjectName(); HsqlName hsqlName = database.nameManager.newHsqlName(token.tokenString, isDelimitedIdentifier(), type); if (token.namePrefix != null) { switch (type) { case SchemaObject.LABEL : case SchemaObject.VARIABLE : case SchemaObject.GRANTEE : case SchemaObject.CATALOG : throw unexpectedToken(); case SchemaObject.CURSOR : { if (token.namePrePrefix == null && !token.isDelimitedPrefix && (Tokens.T_MODULE.equals(token.namePrefix))) { // local } else { throw unexpectedTokenRequire(Tokens.T_MODULE); } break; } case SchemaObject.SCHEMA : { checkValidCatalogName(token.namePrefix); if (token.namePrePrefix != null) { throw tooManyIdentifiers(); } break; } case SchemaObject.SERVER : case SchemaObject.WRAPPER : { checkValidCatalogName(token.namePrefix); if (token.namePrePrefix != null) { throw tooManyIdentifiers(); } break; } case SchemaObject.COLUMN : { throw tooManyIdentifiers(); } default : { checkValidCatalogName(token.namePrePrefix); HsqlName schemaName; if (checkSchema) { schemaName = session.getSchemaHsqlName(token.namePrefix); } else { schemaName = session.database.schemaManager.findSchemaHsqlName( token.namePrefix); if (schemaName == null) { schemaName = database.nameManager.newHsqlName( token.namePrefix, isDelimitedIdentifier(), SchemaObject.SCHEMA); } } hsqlName.setSchemaIfNull(schemaName); break; } } } read(); return hsqlName; } HsqlName readNewDependentSchemaObjectName(HsqlName parentName, int type) { HsqlName name = readNewSchemaObjectName(type, true); name.parent = parentName; name.setSchemaIfNull(parentName.schema); if (name.schema != null && parentName.schema != null && name.schema != parentName.schema) { throw Error.error(ErrorCode.X_42505, token.namePrefix); } return name; } HsqlName readSchemaName() { checkIsSchemaObjectName(); checkValidCatalogName(token.namePrefix); HsqlName schema = session.getSchemaHsqlName(token.tokenString); read(); return schema; } SchemaObject readSchemaObjectName(int type) { checkIsSchemaObjectName(); checkValidCatalogName(token.namePrePrefix); String schema = session.getSchemaName(token.namePrefix); SchemaObject object = database.schemaManager.getSchemaObject(token.tokenString, schema, type); read(); return object; } SchemaObject readSchemaObjectName(HsqlName schemaName, int type) { checkIsSchemaObjectName(); SchemaObject object = database.schemaManager.getSchemaObject(token.tokenString, schemaName.name, type); if (token.namePrefix != null) { if (!token.namePrefix.equals(schemaName.name)) { // todo - better error message throw Error.error(ErrorCode.X_42505, token.namePrefix); } if (token.namePrePrefix != null) { if (!token.namePrePrefix.equals( database.getCatalogName().name)) { // todo - better error message throw Error.error(ErrorCode.X_42505, token.namePrefix); } } } read(); return object; } Table readTableName() { return readTableName(false); } Table readTableName(boolean orSynonym) { checkIsIdentifier(); lastSynonym = null; Table table = database.schemaManager.findTable(session, token.tokenString, token.namePrefix, token.namePrePrefix); if (table == null) { boolean trySynonym = orSynonym && token.namePrefix == null && !isViewDefinition; if (trySynonym) { ReferenceObject reference = database.schemaManager.findSynonym( token.tokenString, session.getCurrentSchemaHsqlName().name, SchemaObject.TABLE); if (reference != null) { table = (Table) database.schemaManager.getSchemaObject( reference.getTarget()); lastSynonym = reference.getName(); } } if (table == null) { throw Error.error(ErrorCode.X_42501, token.tokenString); } } getRecordedToken().setExpression(table); read(); return table; }
Returns a period condition (including a default) for all tables with a system period. Otherwise null;
/** * Returns a period condition (including a default) for all tables with a * system period. Otherwise null; */
ExpressionPeriodOp XreadQuerySystemPeriodSpecOrNull(Table table) { int position = getPosition(); if (!table.isSystemVersioned()) { return null; } if (token.tokenType == Tokens.FOR) { read(); } else { ExpressionPeriodOp periodExpression = new ExpressionPeriodOp(); return periodExpression; } if (token.tokenType == Tokens.SYSTEM_TIME) { read(); } else { rewind(position); return null; } switch (token.tokenType) { case Tokens.AS : { read(); readThis(Tokens.OF); Expression point = XreadValueExpression(); return new ExpressionPeriodOp(point); } case Tokens.BETWEEN : { read(); readIfThis(Tokens.ASYMMETRIC); Expression pointStart = XreadValueExpression(); readThis(Tokens.AND); Expression pointEnd = XreadValueExpression(); return new ExpressionPeriodOp(pointStart, pointEnd); } case Tokens.FROM : { read(); Expression pointStart = XreadValueExpression(); readThis(Tokens.TO); Expression pointEnd = XreadValueExpression(); return new ExpressionPeriodOp(pointStart, pointEnd); } default : throw unexpectedToken(); } } ExpressionPeriodOp XreadQueryApplicationPeriodSpecOrNull(Table table) { PeriodDefinition period = table.getApplicationPeriod(); if (period == null) { return null; } if (token.tokenType == Tokens.FOR) { read(); } else { return null; } readThis(Tokens.PORTION); readThis(Tokens.OF); checkIsSimpleName(); if (!token.tokenString.equals(period.periodName.getNameString())) { throw Error.error(ErrorCode.X_42501, token.tokenString); } read(); readThis(Tokens.FROM); Expression pointStart = XreadValueExpression(); readThis(Tokens.TO); Expression pointEnd = XreadValueExpression(); ExpressionPeriod left = new ExpressionPeriod(period); ExpressionPeriod right = new ExpressionPeriod(pointStart, pointEnd); return new ExpressionPeriodOp(OpTypes.RANGE_OVERLAPS, left, right); } ColumnSchema readSimpleColumnName(RangeVariable rangeVar, boolean withPrefix) { ColumnSchema column = null; checkIsIdentifier(); if (!withPrefix && token.namePrefix != null) { throw tooManyIdentifiers(); } int index = rangeVar.findColumn(token.namePrePrefix, token.namePrefix, token.tokenString); if (index == -1) { throw Error.error(ErrorCode.X_42501, token.tokenString); } column = rangeVar.getTable().getColumn(index); read(); return column; } ColumnSchema readSimpleColumnName(Table table, boolean withPrefix) { checkIsIdentifier(); if (withPrefix) { if (token.namePrefix != null && !table.getName().name.equals(token.namePrefix)) { throw Error.error(ErrorCode.X_42501, token.namePrefix); } } else if (token.namePrefix != null) { throw tooManyIdentifiers(); } int index = table.findColumn(token.tokenString); if (index == -1) { throw Error.error(ErrorCode.X_42501, token.tokenString); } ColumnSchema column = table.getColumn(index); read(); return column; } StatementQuery compileDeclareCursorOrNull(RangeGroup[] rangeGroups, boolean isRoutine) { int sensitivity = ResultConstants.SQL_ASENSITIVE; int scrollability = ResultConstants.SQL_NONSCROLLABLE; int holdability = ResultConstants.SQL_NONHOLDABLE; int returnability = ResultConstants.SQL_WITHOUT_RETURN; int position = getPosition(); readThis(Tokens.DECLARE); HsqlName cursorName = readNewSchemaObjectName(SchemaObject.CURSOR, false); switch (token.tokenType) { case Tokens.SENSITIVE : read(); sensitivity = ResultConstants.SQL_SENSITIVE; break; case Tokens.INSENSITIVE : read(); sensitivity = ResultConstants.SQL_INSENSITIVE; break; case Tokens.ASENSITIVE : read(); break; default : } if (token.tokenType == Tokens.NO) { readThis(Tokens.SCROLL); } else { if (token.tokenType == Tokens.SCROLL) { read(); scrollability = ResultConstants.SQL_SCROLLABLE; } } if (token.tokenType != Tokens.CURSOR) { rewind(position); return null; } readThis(Tokens.CURSOR); for (int round = 0; round < 2; round++) { if (token.tokenType == Tokens.WITH) { read(); if (round == 0 && token.tokenType == Tokens.HOLD) { read(); holdability = ResultConstants.SQL_HOLDABLE; } else { readThis(Tokens.RETURN); round++; returnability = ResultConstants.SQL_WITH_RETURN; } } else if (token.tokenType == Tokens.WITHOUT) { read(); if (round == 0 && token.tokenType == Tokens.HOLD) { read(); } else { readThis(Tokens.RETURN); round++; } } } readThis(Tokens.FOR); int props = ResultProperties.getProperties(sensitivity, ResultConstants.SQL_UPDATABLE, scrollability, holdability, returnability); StatementQuery cs = compileCursorSpecification(rangeGroups, props, isRoutine); cs.setCursorName(cursorName); return cs; }
Retrieves a SELECT or other query expression Statement from this parse context.
/** * Retrieves a SELECT or other query expression Statement from this parse context. */
StatementQuery compileCursorSpecification(RangeGroup[] rangeGroups, int props, boolean isRoutine) { OrderedHashSet colNames = null; QueryExpression queryExpression = XreadQueryExpression(); if (token.tokenType == Tokens.FOR) { read(); if (token.tokenType == Tokens.READ || token.tokenType == Tokens.FETCH) { read(); readThis(Tokens.ONLY); props = ResultProperties.addUpdatable(props, false); } else { readThis(Tokens.UPDATE); props = ResultProperties.addUpdatable(props, true); if (token.tokenType == Tokens.OF) { readThis(Tokens.OF); colNames = new OrderedHashSet(); readColumnNameList(colNames, null, false); } if (database.sqlSyntaxOra) { readIfThis(Tokens.NOWAIT); } } } if (database.sqlSyntaxDb2) { if (readIfThis(Tokens.WITH)) { if (!readIfThis("CS")) { if (!readIfThis("RR")) { if (!readIfThis("RS")) { readThis("UR"); } } } } if (readIfThis(Tokens.USE)) { readThis(Tokens.AND); readThis(Tokens.T_KEEP); if (!readIfThis(Tokens.T_EXCLUSIVE)) { if (!readIfThis(Tokens.T_SHARE)) { readThis(Tokens.UPDATE); } } readThis(Tokens.LOCKS); } } if (ResultProperties.isUpdatable(props)) { queryExpression.isUpdatable = true; } queryExpression.setReturningResult(); queryExpression.resolve(session, rangeGroups, null); StatementQuery cs = isRoutine ? new StatementCursor(session, queryExpression, compileContext) : new StatementQuery(session, queryExpression, compileContext); return cs; } StatementDMQL compileShortCursorSpecification(int props) { QueryExpression select = XreadSimpleTable(); if (ResultProperties.isUpdatable(props)) { select.isUpdatable = true; } select.setReturningResult(); select.resolve(session); StatementDMQL cs = new StatementQuery(session, select, compileContext); return cs; } int readCloseBrackets(int limit) { int count = 0; while (count < limit && token.tokenType == Tokens.CLOSEBRACKET) { read(); count++; } return count; } int readOpenBrackets() { int count = 0; while (token.tokenType == Tokens.OPENBRACKET) { count++; read(); } return count; } void readNestedParenthesisedTokens() { readThis(Tokens.OPENBRACKET); do { read(); if (token.tokenType == Tokens.OPENBRACKET) { readNestedParenthesisedTokens(); } if (token.tokenType == Tokens.X_ENDPARSE) { throw unexpectedToken(); } } while (token.tokenType != Tokens.CLOSEBRACKET); read(); } void checkValidCatalogName(String name) { if (name != null && !name.equals(database.getCatalogName().name)) { throw Error.error(ErrorCode.X_42501, name); } } void rewind(int position) { super.rewind(position); compileContext.rewind(position); } public static final class CompileContext { final Session session; final ParserBase parser; final CompileContext baseContext; final int basePosition; boolean isViewTable; // private int subqueryDepth; private HsqlArrayList namedSubqueries; // private OrderedIntKeyHashMap parameters = new OrderedIntKeyHashMap(); private HsqlArrayList usedSequences = new HsqlArrayList(8, true); private HsqlArrayList usedRoutines = new HsqlArrayList(8, true); private OrderedIntKeyHashMap rangeVariables = new OrderedIntKeyHashMap(); private HsqlArrayList usedObjects = new HsqlArrayList(8, true); Type currentDomain; boolean contextuallyTypedExpression; Routine callProcedure; // private RangeGroup[] outerRangeGroups = RangeGroup.emptyArray; // private final int initialRangeVarIndex; private int rangeVarIndex; public CompileContext(Session session) { this(session, null, null); } public CompileContext(Session session, ParserBase parser, CompileContext baseContext) { this.session = session; this.parser = parser; this.baseContext = baseContext; if (baseContext == null) { initialRangeVarIndex = rangeVarIndex = 1; basePosition = 0; } else { initialRangeVarIndex = rangeVarIndex = baseContext.getRangeVarCount(); basePosition = baseContext.parser.getPosition(); subqueryDepth = baseContext.getDepth(); } } public void reset() { rangeVarIndex = initialRangeVarIndex; subqueryDepth = 0; rangeVariables.clear(); parameters.clear(); usedSequences.clear(); usedRoutines.clear(); callProcedure = null; usedObjects.clear(); outerRangeGroups = RangeGroup.emptyArray; // currentDomain = null; contextuallyTypedExpression = false; } public int getDepth() { return subqueryDepth; } public void incrementDepth() { subqueryDepth++; if (baseContext != null) { baseContext.subqueryDepth++; } } public void decrementDepth() { clearSubqueries(); subqueryDepth--; if (baseContext != null) { baseContext.subqueryDepth--; } } public void decrementDepth(int toDepth) { while (subqueryDepth > toDepth) { decrementDepth(); } } public void rewind(int position) { if (baseContext != null) { baseContext.rewind(basePosition + position); return; } rewindRangeVariables(position); rewindParameters(position); } private void rewindRangeVariables(int position) { for (int i = rangeVariables.size() - 1; i >= 0; i--) { int rangePos = rangeVariables.getKey(i, -1); if (rangePos > position) { rangeVariables.removeKeyAndValue(i); } } if (rangeVariables.size() > 0) { RangeVariable range = (RangeVariable) rangeVariables.getValue( rangeVariables.size() - 1); rangeVarIndex = range.rangePosition + 1; } else { rangeVarIndex = initialRangeVarIndex; } } private void rewindParameters(int position) { if (baseContext != null) { baseContext.rewindParameters(basePosition + position); return; } Iterator it = parameters.keySet().iterator(); while (it.hasNext()) { int pos = it.nextInt(); if (pos >= position) { it.remove(); } } } public void setCurrentSubquery(HsqlName name) { isViewTable = name.type == SchemaObject.VIEW; } public void registerRangeVariable(RangeVariable range) { int nextRangePosition = basePosition; if (parser != null) { nextRangePosition += parser.getPosition(); } if (isViewTable) { range.isViewSubquery = true; } registerRangeVariable(range, nextRangePosition); } private void registerRangeVariable(RangeVariable range, int position) { if (baseContext != null) { baseContext.registerRangeVariable(range, position); return; } range.rangePosition = getNextRangeVarIndex(); range.level = subqueryDepth; rangeVariables.put(position, range); } public void setNextRangeVarIndex(int n) { if (baseContext != null) { baseContext.setNextRangeVarIndex(n); return; } rangeVarIndex = n; } private int getNextRangeVarIndex() { if (baseContext != null) { return baseContext.getNextRangeVarIndex(); } return rangeVarIndex++; } private int test; public int getNextResultRangeVarIndex() { RangeVariable range = new RangeVariable(null, null, false, RangeVariable.PLACEHOLDER_RANGE); registerRangeVariable(range); return range.rangePosition; } public int getRangeVarCount() { if (baseContext != null) { return baseContext.getRangeVarCount(); } return rangeVarIndex; } public RangeVariable[] getAllRangeVariables() { HsqlArrayList list = new HsqlArrayList(); for (int i = 0; i < rangeVariables.size(); i++) { RangeVariable range = (RangeVariable) rangeVariables.getValue(i); if (range.rangeType != RangeVariable.PLACEHOLDER_RANGE) { list.add(range); } } RangeVariable[] array = new RangeVariable[list.size()]; list.toArray(array); return array; } public RangeGroup[] getOuterRanges() { if (baseContext != null) { return baseContext.outerRangeGroups; } return outerRangeGroups; } public void setOuterRanges(RangeGroup[] rangeGroups) { outerRangeGroups = rangeGroups; } public NumberSequence[] getSequences() { if (usedSequences.size() == 0) { return NumberSequence.emptyArray; } NumberSequence[] array = new NumberSequence[usedSequences.size()]; usedSequences.toArray(array); return array; } public Routine[] getRoutines() { if (callProcedure == null && usedRoutines.size() == 0) { return Routine.emptyArray; } OrderedHashSet set = new OrderedHashSet(); for (int i = 0; i < usedRoutines.size(); i++) { FunctionSQLInvoked function = (FunctionSQLInvoked) usedRoutines.get(i); set.add(function.routine); } if (callProcedure != null) { set.add(callProcedure); } Routine[] array = new Routine[set.size()]; set.toArray(array); return array; } private void initSubqueryNames() { if (namedSubqueries == null) { namedSubqueries = new HsqlArrayList(); } if (namedSubqueries.size() <= subqueryDepth) { namedSubqueries.setSize(subqueryDepth + 1); } HashMappedList set = (HashMappedList) namedSubqueries.get(subqueryDepth); if (set == null) { set = new HashMappedList(); namedSubqueries.set(subqueryDepth, set); } } private void clearSubqueries() { if (namedSubqueries != null) { if (namedSubqueries.size() > subqueryDepth) { HashMappedList set = (HashMappedList) namedSubqueries.get(subqueryDepth); if (set != null) { set.clear(); } } } } private void registerSubquery(String name) { initSubqueryNames(); HashMappedList set = (HashMappedList) namedSubqueries.get(subqueryDepth); boolean added = set.add(name, null); if (!added) { throw Error.error(ErrorCode.X_42504, name); } } private void registerSubquery(String name, TableDerived td) { HashMappedList set = (HashMappedList) namedSubqueries.get(subqueryDepth); set.put(name, td); } private void unregisterSubqueries() { if (namedSubqueries == null) { return; } for (int i = subqueryDepth; i < namedSubqueries.size(); i++) { namedSubqueries.set(i, null); } } private TableDerived getNamedSubQuery(String name) { if (baseContext != null) { TableDerived td = baseContext.getNamedSubQuery(name); if (td != null) { return td; } } if (namedSubqueries == null) { return null; } for (int i = subqueryDepth; i >= 0; i--) { if (namedSubqueries.size() <= i) { continue; } HashMappedList set = (HashMappedList) namedSubqueries.get(i); if (set == null) { continue; } TableDerived td = (TableDerived) set.get(name); if (td != null) { return td; } } return null; } private void addParameter(ExpressionColumn e, int position) { e.parameterIndex = parameters.size(); parameters.put(position, e); } private void addSchemaObject(SchemaObject object) { usedObjects.add(object); } private void addSequence(SchemaObject object) { usedSequences.add(object); } void addFunctionCall(FunctionSQLInvoked function) { usedRoutines.add(function); } void addProcedureCall(Routine procedure) { callProcedure = procedure; } ExpressionColumn[] getParameters() { if (parameters.size() == 0) { return ExpressionColumn.emptyArray; } ExpressionColumn[] result = new ExpressionColumn[parameters.size()]; parameters.valuesToArray(result); parameters.clear(); return result; } public OrderedHashSet getSchemaObjectNames() { OrderedHashSet set = new OrderedHashSet(); for (int i = 0; i < usedSequences.size(); i++) { SchemaObject object = (SchemaObject) usedSequences.get(i); set.add(object.getName()); } for (int i = 0; i < usedObjects.size(); i++) { SchemaObject object = (SchemaObject) usedObjects.get(i); set.add(object.getName()); } for (int i = 0; i < rangeVariables.size(); i++) { RangeVariable range = (RangeVariable) rangeVariables.getValue(i); if (range.isViewSubquery) { continue; } if (range.rangeType == RangeVariable.PLACEHOLDER_RANGE) { continue; } HsqlName name = range.rangeTable.getName(); if (name.schema != SqlInvariants.SYSTEM_SCHEMA_HSQLNAME) { set.add(name); set.addAll(range.getColumnNames()); if (range.periodCondition != null) { if (range.periodCondition.isSystemVersionCondition()) { set.add(range.rangeTable.systemPeriod.getName()); } } } else if (name.type == SchemaObject.TRANSITION) { set.addAll(range.getColumnNames()); } } Routine[] routines = getRoutines(); for (int i = 0; i < routines.length; i++) { set.add(routines[i].getSpecificName()); } return set; } } }