/* Copyright (c) 2001-2018, 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.4.1
* @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.
*
* @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.
*
* @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 :
typeNumber =
Types.
SQL_DECIMAL;
break;
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 (
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;
}
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;
}
}
if (
typeNumber ==
Types.
SQL_TIMESTAMP
||
typeNumber ==
Types.
SQL_TIME) {
if (
length >
DTIType.
maxFractionPrecision) {
throw
Error.
error(
ErrorCode.
X_42592);
}
scale = (int)
length;
length = 0;
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;
}
}
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();
checkIsSimpleName();
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.
*
* @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) {
read();
checkIsNonCoreReservedIdentifier();
}
if (
isNonCoreReservedIdentifier()) {
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);
SimpleName alias = null;
if (
operation !=
StatementTypes.
TRUNCATE) {
if (
token.
tokenType ==
Tokens.
AS) {
read();
checkIsNonCoreReservedIdentifier();
}
if (
isNonCoreReservedIdentifier()
&& (!
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);
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. <p>
*/
protected
RangeVariable readTableOrSubquery() {
Table table = null;
SimpleName alias = null;
SimpleName[]
columnNameList = null;
OrderedHashSet columnList = 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;
}
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 (
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) {
int
position =
getPosition();
if (
token.
tokenType ==
Tokens.
FILTER) {
read();
if (
token.
tokenType !=
Tokens.
OPENBRACKET) {
rewind(
position);
return;
}
readThis(
Tokens.
OPENBRACKET);
readThis(
Tokens.
WHERE);
Expression condition =
XreadBooleanValueExpression();
e.
setCondition(
condition);
readThis(
Tokens.
CLOSEBRACKET);
}
}
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;
break;
} 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;
boolean
isRow = false;
boolean
isPeriod = false;
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);
readThis(
Tokens.
CLOSEBRACKET);
e.
setSubType(
OpTypes.
RANGE_EQUALS);
} 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);
isRow = true;
} else if (
token.
tokenType ==
Tokens.
PERIOD) {
read();
checkIsThis(
Tokens.
OPENBRACKET);
isPeriod = true;
}
if (
token.
tokenType ==
Tokens.
OPENBRACKET) {
read();
// ignore isRow
e =
XreadRowElementList(true);
readThis(
Tokens.
CLOSEBRACKET);
if (
isPeriod) {
e.
setSubType(
OpTypes.
RANGE_EQUALS);
}
}
}
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;
}
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.
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 =
readCastExpressionOrNull();
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;
}
default :
e =
XreadAllTypesValueExpressionPrimary(
boole);
}
e =
XreadModifier(
e);
return
e;
}
Expression XreadModifier(
Expression e) {
switch (
token.
tokenType) {
case
Tokens.
AT : {
read();
Expression e1 = null;
if (
token.
tokenType ==
Tokens.
LOCAL) {
read();
} else {
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 :
}
}
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 =
XreadValueExpressionOrNull();
compileContext.
contextuallyTypedExpression = false;
return
e;
}
Expression XreadValueExpressionOrNull() {
Expression e =
XreadAllTypesCommonValueExpression(true);
if (
e == null) {
return null;
}
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 ? (
Expression) 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 ? (
Expression) 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;
}
default :
}
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;
}
default :
}
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
*/
private
ExpressionLogical XreadPeriodPredicateRightPart(int
opType,
Expression l) {
if (
l.
getType() !=
OpTypes.
ROW) {
throw
Error.
error(
ErrorCode.
X_42564);
}
if (
l.
nodes.length != 2) {
throw
Error.
error(
ErrorCode.
X_42564);
}
if (
opType !=
OpTypes.
RANGE_OVERLAPS) {
if (
l.
getSubType() !=
OpTypes.
RANGE_EQUALS) {
throw
unexpectedTokenRequire(
Tokens.
T_PERIOD);
}
}
read();
boolean
period = false;
if (
token.
tokenType ==
Tokens.
PERIOD) {
read();
period = true;
if (
token.
tokenType !=
Tokens.
OPENBRACKET) {
throw
unexpectedTokenRequire(
Tokens.
T_OPENBRACKET);
}
}
Expression r =
XreadRowValuePredicand();
if (
period) {
if (
r.
nodes.length == 2) {
r.
setSubType(
OpTypes.
RANGE_EQUALS);
} else {
throw
Error.
error(
ErrorCode.
X_42564);
}
}
if (
r.
nodes.length == 2) {
if (
opType ==
OpTypes.
RANGE_OVERLAPS) {
if (
period) {
if (
l.
getSubType() !=
OpTypes.
RANGE_EQUALS) {
throw
unexpectedTokenRequire(
Tokens.
T_PERIOD);
}
}
} else {
if (!
period) {
throw
unexpectedTokenRequire(
Tokens.
T_PERIOD);
}
}
} else if (
r.
nodes.length < 2) {
if (
opType !=
OpTypes.
RANGE_CONTAINS) {
throw
Error.
error(
ErrorCode.
X_42564);
}
} else {
throw
Error.
error(
ErrorCode.
X_42564);
}
return new
ExpressionLogical(
opType,
l,
r);
}
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 (
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
*/
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
*/
private
Expression readCaseWhenExpressionOrNull() {
Expression l = null;
int
position =
getPosition();
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 or CONVERT expression
*/
private
Expression readCastExpressionOrNull() {
Expression e;
Type typeObject;
int
position =
getPosition();
read();
readThis(
Tokens.
OPENBRACKET);
e =
XreadValueExpressionOrNull();
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 =
XreadValueExpressionOrNull();
if (
readIfThis(
Tokens.
COMMA)) {
mode = this.
XreadSimpleValueSpecificationOrNull();
}
} else {
e =
XreadValueExpressionOrNull();
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
*/
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 =
XreadValueExpressionOrNull();
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
*/
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
*/
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
*/
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
*/
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();
continue;
}
}
}
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;
}
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.
*/
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());
} 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;
}
}
}