org.hsqldb.ParserTable Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sqltool Show documentation
Show all versions of sqltool Show documentation
HSQLDB - Lightweight 100% Java SQL Database Engine
/* Copyright (c) 2001-2020, 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.error.Error;
import org.hsqldb.error.ErrorCode;
import org.hsqldb.index.Index;
import org.hsqldb.lib.HashMappedList;
import org.hsqldb.lib.HsqlArrayList;
import org.hsqldb.lib.OrderedHashSet;
import org.hsqldb.lib.OrderedIntHashSet;
import org.hsqldb.types.BinaryData;
import org.hsqldb.types.Type;
import org.hsqldb.types.Types;
/**
* Parser for SQL table definition
*
* @author Fred Toussi (fredt@users dot sourceforge.net)
* @version 2.5.1
* @since 1.9.0
*/
public class ParserTable extends ParserDML {
ParserTable(Session session, Scanner scanner) {
super(session, scanner);
}
StatementSchema compileCreateTable(int type) {
boolean ifNot = readIfNotExists();
HsqlName name = readNewSchemaObjectName(SchemaObject.TABLE, false);
name.setSchemaIfNull(session.getCurrentSchemaHsqlName());
Table table;
switch (type) {
case TableBase.TEMP_TEXT_TABLE :
case TableBase.TEXT_TABLE : {
table = new TextTable(database, name, type);
break;
}
default : {
table = new Table(database, name, type);
}
}
if (token.tokenType == Tokens.AS) {
return compileCreateTableAsSubqueryDefinition(table);
}
return compileCreateTableBody(table, ifNot);
}
StatementSchema compileCreateTableBody(Table table, boolean ifNot) {
HsqlArrayList tempConstraints = new HsqlArrayList();
HsqlArrayList tempIndexes = new HsqlArrayList();
Statement statement = null;
HsqlName[] readLockNames = null;
boolean isTable = readTableContentsSource(table, tempConstraints,
tempIndexes);
if (!isTable) {
return compileCreateTableAsSubqueryDefinition(table);
}
readTableVersioningClause(table);
if (token.tokenType == Tokens.AS) {
read();
QueryExpression queryExpression = null;
queryExpression = readTableQuery();
readThis(Tokens.WITH);
readThis(Tokens.DATA);
statement = new StatementQuery(session, queryExpression,
compileContext);
readLockNames = statement.getTableNamesForRead();
Type[] dataTypes = queryExpression.getColumnTypes();
if (table.getColumnCount() != dataTypes.length) {
throw Error.error(ErrorCode.X_42593);
}
for (int i = 0; i < dataTypes.length; i++) {
boolean b = table.getColumn(i).getDataType().canBeAssignedFrom(
dataTypes[i]);
if (!b) {
throw Error.error(ErrorCode.X_42561);
}
}
}
readTableOnCommitClause(table);
if (database.sqlSyntaxMys) {
HashMappedList list = super.readPropertyValuePairs(true, false);
if (list != null) {
Token value = (Token) list.get(Tokens.T_COMMENT);
if (value != null) {
String comment = value.tokenString;
table.getName().comment = comment;
}
}
}
OrderedHashSet names = new OrderedHashSet();
names.add(database.getCatalogName());
for (int i = 0; i < tempConstraints.size(); i++) {
Constraint c = (Constraint) tempConstraints.get(i);
HsqlName name = c.getMainTableName();
if (name != null) {
Table t = database.schemaManager.findUserTable(name.name,
name.schema.name);
if (t != null && !t.isTemp()) {
names.add(table.getName());
}
}
}
String sql = getLastPart();
Object[] args = new Object[] {
table, tempConstraints, tempIndexes, statement,
Boolean.valueOf(ifNot)
};
HsqlName[] writeLockNames = new HsqlName[names.size()];
names.toArray(writeLockNames);
return new StatementSchema(sql, StatementTypes.CREATE_TABLE, args,
readLockNames, writeLockNames);
}
boolean readTableContentsSource(Table table,
HsqlArrayList tempConstraints,
HsqlArrayList tempIndexes) {
int position = getPosition();
readThis(Tokens.OPENBRACKET);
Constraint c = new Constraint(null, null,
SchemaObject.ConstraintTypes.TEMP);
tempConstraints.add(c);
boolean start = true;
boolean startPart = true;
boolean end = false;
boolean hasRowStart = false;
boolean hasRowEnd = false;
while (!end) {
switch (token.tokenType) {
case Tokens.LIKE : {
ColumnSchema[] likeColumns = readLikeTable(table);
for (int i = 0; i < likeColumns.length; i++) {
table.addColumn(likeColumns[i]);
}
start = false;
startPart = false;
continue;
}
case Tokens.CONSTRAINT :
case Tokens.PRIMARY :
case Tokens.FOREIGN :
case Tokens.UNIQUE :
case Tokens.CHECK :
if (!startPart) {
throw unexpectedToken();
}
readConstraint(table, tempConstraints);
start = false;
startPart = false;
continue;
case Tokens.PERIOD :
if (!startPart) {
throw unexpectedToken();
}
if (table.isTemp() || table.isText()) {
throw unexpectedToken();
}
PeriodDefinition period = readAndAddPeriod(table);
if (period == null) {
break;
}
start = false;
startPart = false;
continue;
case Tokens.COMMA :
if (startPart) {
throw unexpectedToken();
}
read();
startPart = true;
continue;
case Tokens.CLOSEBRACKET :
read();
end = true;
continue;
case Tokens.KEY :
case Tokens.INDEX :
if (database.sqlSyntaxMys) {
readIndex(table, tempIndexes);
start = false;
startPart = false;
continue;
}
}
if (!startPart) {
throw unexpectedToken();
}
checkIsSchemaObjectName();
HsqlName hsqlName =
database.nameManager.newColumnHsqlName(table.getName(),
token.tokenString, isDelimitedIdentifier());
read();
ColumnSchema newcolumn = readColumnDefinitionOrNull(table,
hsqlName, tempConstraints);
if (newcolumn == null) {
if (start) {
rewind(position);
return false;
} else {
throw Error.error(ErrorCode.X_42000);
}
}
table.addColumn(newcolumn);
start = false;
startPart = false;
if (newcolumn.getSystemPeriodType()
== SchemaObject.PeriodSystemColumnType.PERIOD_ROW_START) {
if (hasRowStart) {
throw Error.error(ErrorCode.X_42591);
}
hasRowStart = true;
} else if (newcolumn.getSystemPeriodType()
== SchemaObject.PeriodSystemColumnType.PERIOD_ROW_END) {
if (hasRowEnd) {
throw Error.error(ErrorCode.X_42591);
}
hasRowEnd = true;
}
}
if (table.getColumnCount() == 0) {
throw Error.error(ErrorCode.X_42591);
}
if (hasRowStart ^ hasRowEnd) {
throw Error.error(ErrorCode.X_42516);
}
if (hasRowStart && table.systemPeriod == null) {
throw Error.error(ErrorCode.X_42516);
}
setPeriodColumns(table, table.systemPeriod);
setPeriodColumns(table, table.applicationPeriod);
// not supported
if (table.applicationPeriod != null) {
throw Error.error(ErrorCode.X_0A501,
table.applicationPeriod.getName().name);
}
return true;
}
/**
* check period columns have already been defined in table and have the
* supported data types
*/
void setPeriodColumns(Table table, PeriodDefinition period) {
if (period == null) {
return;
}
OrderedHashSet set = period.columnNames;
ColumnSchema startColumn = null;
ColumnSchema endColumn = null;
HsqlName name = period.getName();
int index = table.findColumn(name.name);
if (index >= 0) {
throw Error.error(ErrorCode.X_42516, name.name);
}
for (int i = 0; i < 2; i++) {
String columnName = (String) set.get(i);
index = table.findColumn(columnName);
if (index < 0) {
throw Error.error(ErrorCode.X_42501, columnName);
}
ColumnSchema column = table.getColumn(index);
Type type = column.getDataType();
switch (period.periodType) {
case SchemaObject.PeriodType.PERIOD_SYSTEM :
if (!type.isTimestampType()) {
throw Error.error(ErrorCode.X_42516, columnName);
}
if (i == 0) {
if (column.getSystemPeriodType()
!= SchemaObject.PeriodSystemColumnType
.PERIOD_ROW_START) {
throw Error.error(ErrorCode.X_42516, columnName);
}
} else {
if (column.getSystemPeriodType()
!= SchemaObject.PeriodSystemColumnType
.PERIOD_ROW_END) {
throw Error.error(ErrorCode.X_42516, columnName);
}
}
break;
case SchemaObject.PeriodType.PERIOD_APPLICATION :
if (!type.isDateOrTimestampType()) {
throw Error.error(ErrorCode.X_42516, columnName);
}
break;
}
if (i == 0) {
startColumn = column;
} else {
endColumn = column;
if (!startColumn.getDataType().equals(
endColumn.getDataType())) {
throw Error.error(ErrorCode.X_42516, columnName);
}
}
}
period.startColumn = startColumn;
period.endColumn = endColumn;
}
/**
* check the system period name and column names do not exist
*/
void checkPeriodColumnsAdd(Table table, PeriodDefinition period) {
if (period == null) {
return;
}
OrderedHashSet set = period.columnNames;
HsqlName name = period.getName();
int index = table.findColumn(name.name);
if (index >= 0) {
throw Error.error(ErrorCode.X_42516, name.name);
}
for (int i = 0; i < 2; i++) {
String columnName = (String) set.get(i);
index = table.findColumn(columnName);
if (index >= 0) {
throw Error.error(ErrorCode.X_42504, columnName);
}
}
}
void readTableVersioningClause(Table table) {
if (table.systemPeriod != null) {
if (readIfThis(Tokens.WITH)) {
readThis(Tokens.SYSTEM);
readThis(Tokens.VERSIONING);
table.isSystemVersioned = true;
}
}
}
void readTableOnCommitClause(Table table) {
if (token.tokenType == Tokens.ON) {
if (!table.isTemp()) {
throw unexpectedToken();
}
read();
readThis(Tokens.COMMIT);
if (token.tokenType == Tokens.DELETE) {}
else if (token.tokenType == Tokens.PRESERVE) {
table.persistenceScope = TableBase.SCOPE_SESSION;
}
read();
readThis(Tokens.ROWS);
}
}
private ColumnSchema[] readLikeTable(Table table) {
read();
boolean generated = false;
boolean identity = false;
boolean defaults = false;
Table likeTable = readTableName();
OrderedIntHashSet set = new OrderedIntHashSet();
while (true) {
boolean including = token.tokenType == Tokens.INCLUDING;
if (!including && token.tokenType != Tokens.EXCLUDING) {
break;
}
read();
switch (token.tokenType) {
case Tokens.GENERATED :
if (!set.add(token.tokenType)) {
throw unexpectedToken();
}
generated = including;
break;
case Tokens.IDENTITY :
if (!set.add(token.tokenType)) {
throw unexpectedToken();
}
identity = including;
break;
case Tokens.DEFAULTS :
if (!set.add(token.tokenType)) {
throw unexpectedToken();
}
defaults = including;
break;
default :
throw unexpectedToken();
}
read();
}
ColumnSchema[] columnList =
new ColumnSchema[likeTable.getColumnCount()];
for (int i = 0; i < columnList.length; i++) {
ColumnSchema column = likeTable.getColumn(i).duplicate();
HsqlName name =
database.nameManager.newColumnSchemaHsqlName(table.getName(),
column.getName());
column.setName(name);
column.setPrimaryKey(false);
if (identity) {
if (column.isIdentity()) {
column.setIdentity(
column.getIdentitySequence().duplicate());
}
} else {
column.setIdentity(null);
}
if (!defaults) {
column.setDefaultExpression(null);
}
if (!generated) {
column.setGeneratingExpression(null);
}
columnList[i] = column;
}
return columnList;
}
StatementSchema compileCreateTableAsSubqueryDefinition(Table table) {
HsqlName[] readName = null;
boolean withData = true;
HsqlName[] columnNames = null;
Statement statement = null;
QueryExpression queryExpression = null;
if (token.tokenType == Tokens.OPENBRACKET) {
columnNames = readColumnNames(table.getName());
}
readThis(Tokens.AS);
queryExpression = readTableQuery();
readThis(Tokens.WITH);
if (token.tokenType == Tokens.NO) {
read();
withData = false;
} else if (table.getTableType() == TableBase.TEXT_TABLE) {
throw unexpectedTokenRequire(Tokens.T_NO);
}
readThis(Tokens.DATA);
if (token.tokenType == Tokens.ON) {
if (!table.isTemp()) {
throw unexpectedToken();
}
read();
readThis(Tokens.COMMIT);
if (token.tokenType == Tokens.DELETE) {}
else if (token.tokenType == Tokens.PRESERVE) {
table.persistenceScope = TableBase.SCOPE_SESSION;
}
read();
readThis(Tokens.ROWS);
}
if (columnNames == null) {
columnNames = queryExpression.getResultColumnNames();
} else {
if (columnNames.length != queryExpression.getColumnCount()) {
throw Error.error(ErrorCode.X_42593);
}
}
TableUtil.setColumnsInSchemaTable(table, columnNames,
queryExpression.getColumnTypes());
table.createPrimaryKey();
if (table.isTemp() && table.hasLobColumn()) {
throw Error.error(ErrorCode.X_42534);
}
if (withData) {
statement = new StatementQuery(session, queryExpression,
compileContext);
readName = statement.getTableNamesForRead();
}
Object[] args = new Object[] {
table, new HsqlArrayList(), new HsqlArrayList(), statement,
Boolean.FALSE
};
String sql = getLastPart();
HsqlName[] writeLockNames = database.schemaManager.catalogNameArray;
StatementSchema st = new StatementSchema(sql,
StatementTypes.CREATE_TABLE, args, readName, writeLockNames);
return st;
}
private QueryExpression readTableQuery() {
readThis(Tokens.OPENBRACKET);
QueryExpression queryExpression = XreadQueryExpression();
queryExpression.setReturningResult();
queryExpression.resolve(session);
readThis(Tokens.CLOSEBRACKET);
return queryExpression;
}
/**
* Adds a list of temp constraints to a new table
*/
static Table addTableConstraintDefinitions(Session session, Table table,
HsqlArrayList tempConstraints, HsqlArrayList constraintList,
boolean addToSchema) {
Constraint c = (Constraint) tempConstraints.get(0);
HsqlName indexName =
session.database.nameManager.newConstraintIndexName(
table.getName(), c.getName(),
session.database.sqlSysIndexNames);
c.setColumnsIndexes(table);
table.createPrimaryKey(indexName, c.core.mainCols, true);
if (c.core.mainCols != null) {
Constraint newconstraint = new Constraint(c.getName(), table,
table.getPrimaryIndex(),
SchemaObject.ConstraintTypes.PRIMARY_KEY);
table.addConstraint(newconstraint);
if (addToSchema) {
session.database.schemaManager.addSchemaObject(newconstraint);
}
}
for (int i = 1; i < tempConstraints.size(); i++) {
c = (Constraint) tempConstraints.get(i);
switch (c.getConstraintType()) {
case SchemaObject.ConstraintTypes.UNIQUE : {
c.setColumnsIndexes(table);
if (table.getUniqueConstraintForColumns(c.core.mainCols)
!= null) {
throw Error.error(ErrorCode.X_42522);
}
// create an autonamed index
indexName =
session.database.nameManager.newConstraintIndexName(
table.getName(), c.getName(),
session.database.sqlSysIndexNames);
Index index = table.createAndAddIndexStructure(session,
indexName, c.core.mainCols, null, null, true, true,
false);
Constraint newconstraint = new Constraint(c.getName(),
table, index, SchemaObject.ConstraintTypes.UNIQUE);
table.addConstraint(newconstraint);
if (addToSchema) {
session.database.schemaManager.addSchemaObject(
newconstraint);
}
break;
}
case SchemaObject.ConstraintTypes.FOREIGN_KEY : {
addForeignKey(session, table, c, constraintList);
break;
}
case SchemaObject.ConstraintTypes.CHECK : {
try {
c.prepareCheckConstraint(session, table);
} catch (HsqlException e) {
if (session.isProcessingScript()) {
break;
}
throw e;
}
table.addConstraint(c);
if (c.isNotNull()) {
ColumnSchema column =
table.getColumn(c.notNullColumnIndex);
column.setNullable(false);
table.setColumnTypeVars(c.notNullColumnIndex);
}
if (addToSchema) {
session.database.schemaManager.addSchemaObject(c);
}
break;
}
}
}
return table;
}
static void addForeignKey(Session session, Table table, Constraint c,
HsqlArrayList constraintList) {
HsqlName mainTableName = c.getMainTableName();
if (mainTableName == table.getName()) {
c.core.mainTable = table;
} else {
Table mainTable = session.database.schemaManager.findUserTable(
mainTableName.name, mainTableName.schema.name);
if (mainTable == null) {
if (constraintList == null) {
throw Error.error(ErrorCode.X_42501, mainTableName.name);
}
constraintList.add(c);
return;
}
c.core.mainTable = mainTable;
}
c.setColumnsIndexes(table);
TableWorks tableWorks = new TableWorks(session, table);
tableWorks.checkCreateForeignKey(table, c);
Constraint uniqueConstraint =
c.core.mainTable.getUniqueConstraintForColumns(c.core.mainCols);
if (uniqueConstraint == null) {
throw Error.error(ErrorCode.X_42523);
}
Index mainIndex = uniqueConstraint.getMainIndex();
boolean isForward = c.core.mainTable.getSchemaName()
!= table.getSchemaName();
int offset = session.database.schemaManager.getTableIndex(table);
if (offset != -1
&& offset
< session.database.schemaManager.getTableIndex(
c.core.mainTable)) {
isForward = true;
}
HsqlName refIndexName =
session.database.nameManager.newConstraintIndexName(
table.getName(), c.getName(),
session.database.sqlSysIndexNames);
Index index = table.createAndAddIndexStructure(session, refIndexName,
c.core.refCols, null, null, false, true, isForward);
HsqlName mainName = session.database.nameManager.newAutoName("REF",
c.getName().name, table.getSchemaName(), table.getName(),
SchemaObject.INDEX);
c.core.uniqueName = uniqueConstraint.getName();
c.core.mainName = mainName;
c.core.mainIndex = mainIndex;
c.core.refTable = table;
c.core.refName = c.getName();
c.core.refIndex = index;
c.isForward = isForward;
table.addConstraint(c);
c.core.mainTable.addConstraint(new Constraint(mainName, c));
session.database.schemaManager.addSchemaObject(c);
}
Constraint readFKReferences(Table refTable, HsqlName constraintName,
OrderedHashSet refColSet) {
HsqlName mainTableName;
OrderedHashSet mainColSet = null;
readThis(Tokens.REFERENCES);
HsqlName schema;
if (token.namePrefix == null) {
schema = refTable.getSchemaName();
} else {
schema =
database.schemaManager.getSchemaHsqlName(token.namePrefix);
}
if (refTable.getSchemaName() == schema
&& refTable.getName().name.equals(token.tokenString)) {
mainTableName = refTable.getName();
read();
} else {
mainTableName = readFKTableName(schema);
}
if (token.tokenType == Tokens.OPENBRACKET) {
mainColSet = readColumnNames(false);
}
int matchType = OpTypes.MATCH_SIMPLE;
if (token.tokenType == Tokens.MATCH) {
read();
switch (token.tokenType) {
case Tokens.SIMPLE :
read();
break;
case Tokens.PARTIAL :
throw unsupportedFeature();
case Tokens.FULL :
read();
matchType = OpTypes.MATCH_FULL;
break;
default :
throw unexpectedToken();
}
}
// -- In a while loop we parse a maximium of two
// -- "ON" statements following the foreign key
// -- definition this can be
// -- ON [UPDATE|DELETE] [NO ACTION|RESTRICT|CASCADE|SET [NULL|DEFAULT]]
int deleteAction = SchemaObject.ReferentialAction.NO_ACTION;
int updateAction = SchemaObject.ReferentialAction.NO_ACTION;
OrderedIntHashSet set = new OrderedIntHashSet();
while (token.tokenType == Tokens.ON) {
read();
if (!set.add(token.tokenType)) {
throw unexpectedToken();
}
if (token.tokenType == Tokens.DELETE) {
read();
if (token.tokenType == Tokens.SET) {
read();
switch (token.tokenType) {
case Tokens.DEFAULT : {
read();
deleteAction =
SchemaObject.ReferentialAction.SET_DEFAULT;
break;
}
case Tokens.NULL :
read();
deleteAction =
SchemaObject.ReferentialAction.SET_NULL;
break;
default :
throw unexpectedToken();
}
} else if (token.tokenType == Tokens.CASCADE) {
read();
deleteAction = SchemaObject.ReferentialAction.CASCADE;
} else if (token.tokenType == Tokens.RESTRICT) {
read();
} else {
readThis(Tokens.NO);
readThis(Tokens.ACTION);
}
} else if (token.tokenType == Tokens.UPDATE) {
read();
if (token.tokenType == Tokens.SET) {
read();
switch (token.tokenType) {
case Tokens.DEFAULT : {
read();
updateAction =
SchemaObject.ReferentialAction.SET_DEFAULT;
break;
}
case Tokens.NULL :
read();
updateAction =
SchemaObject.ReferentialAction.SET_NULL;
break;
default :
throw unexpectedToken();
}
} else if (token.tokenType == Tokens.CASCADE) {
read();
updateAction = SchemaObject.ReferentialAction.CASCADE;
} else if (token.tokenType == Tokens.RESTRICT) {
read();
} else {
readThis(Tokens.NO);
readThis(Tokens.ACTION);
}
} else {
throw unexpectedToken();
}
}
if (readIfThis(Tokens.NOT)) {
readThis(Tokens.DEFERRABLE);
}
if (constraintName == null) {
constraintName = database.nameManager.newAutoName("FK",
refTable.getSchemaName(), refTable.getName(),
SchemaObject.CONSTRAINT);
}
return new Constraint(constraintName, refTable.getName(), refColSet,
mainTableName, mainColSet,
SchemaObject.ConstraintTypes.FOREIGN_KEY,
deleteAction, updateAction, matchType);
}
HsqlName readFKTableName(HsqlName schema) {
HsqlName name;
checkIsSchemaObjectName();
Table table = database.schemaManager.findUserTable(token.tokenString,
schema.name);
if (table == null) {
name = database.nameManager.newHsqlName(schema, token.tokenString,
isDelimitedIdentifier(), SchemaObject.TABLE);
} else {
name = table.getName();
}
read();
return name;
}
/**
* Responsible for handling the creation of table columns during the process
* of executing CREATE TABLE or ADD COLUMN etc. statements.
*
* @param table this table
* @param hsqlName column name
* @param constraintList list of constraints
* @return a Column object with indicated attributes
*/
ColumnSchema readColumnDefinitionOrNull(Table table, HsqlName hsqlName,
HsqlArrayList constraintList) {
boolean isGenerated = false;
boolean isIdentity = false;
boolean isPKIdentity = false;
boolean generatedAlways = false;
Expression generateExpr = null;
int sysPeriodType =
SchemaObject.PeriodSystemColumnType.PERIOD_ROW_NONE;
boolean isNullable = true;
Expression defaultExpr = null;
Type typeObject = null;
NumberSequence sequence = null;
switch (token.tokenType) {
case Tokens.GENERATED : {
read();
readThis(Tokens.ALWAYS);
isGenerated = true;
generatedAlways = true;
// not yet supported - type determination required
throw unexpectedToken(Tokens.T_GENERATED);
}
case Tokens.IDENTITY : {
read();
isIdentity = true;
isPKIdentity = true;
typeObject = Type.SQL_INTEGER;
sequence = new NumberSequence(null, 0, 1, typeObject);
break;
}
case Tokens.COMMA : {
return null;
}
case Tokens.CLOSEBRACKET : {
return null;
}
default : {
if (token.isUndelimitedIdentifier) {
if (Tokens.T_SERIAL.equals(token.tokenString)) {
if (database.sqlSyntaxMys) {
read();
isIdentity = true;
isPKIdentity = true;
typeObject = Type.SQL_BIGINT;
sequence = new NumberSequence(null, 1, 1,
typeObject);
break;
} else if (database.sqlSyntaxPgs) {
read();
isIdentity = true;
typeObject = Type.SQL_INTEGER;
sequence = new NumberSequence(null, 1, 1,
typeObject);
break;
}
} else if (Tokens.T_BIGSERIAL.equals(token.tokenString)) {
if (database.sqlSyntaxPgs) {
read();
isIdentity = true;
isPKIdentity = true;
typeObject = Type.SQL_BIGINT;
sequence = new NumberSequence(null, 1, 1,
typeObject);
break;
}
}
}
typeObject = readTypeDefinition(true, true);
}
}
if (!isGenerated && !isIdentity) {
if (database.sqlSyntaxMys) {
switch (token.tokenType) {
case Tokens.NULL :
read();
break;
case Tokens.NOT :
read();
readThis(Tokens.NULL);
isNullable = false;
break;
default :
}
}
switch (token.tokenType) {
case Tokens.WITH : {
if (database.sqlSyntaxDb2) {
read();
} else {
throw unexpectedToken();
}
}
// fall through
case Tokens.DEFAULT : {
read();
defaultExpr = readDefaultClause(typeObject);
if (defaultExpr.opType == OpTypes.SEQUENCE) {
if (database.sqlSyntaxPgs) {
sequence =
((ExpressionColumn) defaultExpr).sequence;
defaultExpr = null;
isIdentity = true;
}
}
break;
}
case Tokens.GENERATED : {
read();
if (token.tokenType == Tokens.BY) {
read();
readThis(Tokens.DEFAULT);
} else {
readThis(Tokens.ALWAYS);
generatedAlways = true;
}
readThis(Tokens.AS);
switch (token.tokenType) {
case Tokens.IDENTITY : {
read();
sequence = new NumberSequence(null, typeObject);
sequence.setAlways(generatedAlways);
if (token.tokenType == Tokens.OPENBRACKET) {
read();
readSequenceOptions(sequence, false, false,
true);
readThis(Tokens.CLOSEBRACKET);
}
isIdentity = true;
break;
}
case Tokens.OPENBRACKET : {
if (!generatedAlways) {
throw unexpectedToken(Tokens.GENERATED);
}
isGenerated = true;
read();
generateExpr = XreadValueExpression();
readThis(Tokens.CLOSEBRACKET);
break;
}
case Tokens.SEQUENCE : {
if (generatedAlways) {
throw unexpectedToken();
}
read();
if (token.namePrefix != null) {
if (!token.namePrefix.equals(
table.getSchemaName().name)) {
throw unexpectedToken(token.namePrefix);
}
}
sequence = database.schemaManager.getSequence(
token.tokenString, table.getSchemaName().name,
true);
isIdentity = true;
read();
break;
}
case Tokens.ROW : {
if (!typeObject.isTimestampType()) {
throw unexpectedToken();
}
read();
if (readIfThis(Tokens.START)) {
sysPeriodType =
SchemaObject.PeriodSystemColumnType
.PERIOD_ROW_START;
} else {
readThis(Tokens.END);
sysPeriodType =
SchemaObject.PeriodSystemColumnType
.PERIOD_ROW_END;
}
// always with TIME_ZONE and microsecond precision
if (typeObject.typeCode == Types.SQL_TIMESTAMP) {
typeObject = Type.SQL_TIMESTAMP_WITH_TIME_ZONE;
}
break;
}
}
break;
}
case Tokens.IDENTITY : {
read();
isIdentity = true;
isPKIdentity = true;
sequence = new NumberSequence(null, 0, 1, typeObject);
}
break;
}
}
if (!isGenerated && !isIdentity) {
if (database.sqlSyntaxMys) {
if (token.isUndelimitedIdentifier
&& Tokens.T_AUTO_INCREMENT.equals(token.tokenString)) {
read();
isIdentity = true;
sequence = new NumberSequence(null, 1, 1, typeObject);
}
}
}
ColumnSchema column = new ColumnSchema(hsqlName, typeObject,
isNullable, false, defaultExpr);
if (database.sqlSyntaxMys && typeObject.isDomainType()
&& typeObject.getName().name.equals("ENUM")) {
typeObject.userTypeModifier = null;
HsqlName constName = database.nameManager.newAutoName("CT",
table.getSchemaName(), table.getName(),
SchemaObject.CONSTRAINT);
Constraint c = new Constraint(constName, null,
SchemaObject.ConstraintTypes.CHECK);
constraintList.add(c);
readThis(Tokens.OPENBRACKET);
Expression left = new ExpressionColumn(column);
Expression right = super.XreadInValueListConstructor(1);
readThis(Tokens.CLOSEBRACKET);
ExpressionLogical in = new ExpressionLogical(OpTypes.IN, left,
right);
in.noOptimisation = true;
c.check = in;
}
column.setGeneratingExpression(generateExpr);
column.setSystemPeriodType(sysPeriodType);
readColumnConstraints(table, column, constraintList);
if (token.tokenType == Tokens.IDENTITY && !isIdentity) {
read();
isIdentity = true;
isPKIdentity = true;
sequence = new NumberSequence(null, 0, 1, typeObject);
}
// non-standard GENERATED after constraints
if (token.tokenType == Tokens.GENERATED && !isIdentity
&& !isGenerated) {
read();
if (token.tokenType == Tokens.BY) {
read();
readThis(Tokens.DEFAULT);
} else {
readThis(Tokens.ALWAYS);
generatedAlways = true;
}
readThis(Tokens.AS);
readThis(Tokens.IDENTITY);
sequence = new NumberSequence(null, typeObject);
sequence.setAlways(generatedAlways);
if (token.tokenType == Tokens.OPENBRACKET) {
read();
readSequenceOptions(sequence, false, false, true);
readThis(Tokens.CLOSEBRACKET);
}
isIdentity = true;
}
if (isIdentity) {
column.setIdentity(sequence);
}
if (isPKIdentity && !column.isPrimaryKey()) {
OrderedHashSet set = new OrderedHashSet();
set.add(column.getName().name);
HsqlName constName = database.nameManager.newAutoName("PK",
table.getSchemaName(), table.getName(),
SchemaObject.CONSTRAINT);
Constraint c =
new Constraint(constName, set,
SchemaObject.ConstraintTypes.PRIMARY_KEY);
c.setSimpleIdentityPK();
constraintList.set(0, c);
column.setPrimaryKey(true);
}
if (database.sqlSyntaxPgs && token.tokenType == Tokens.DEFAULT
&& column.getDefaultExpression() == null
&& column.getIdentitySequence() == null) {
read();
defaultExpr = readDefaultClause(typeObject);
if (defaultExpr.opType == OpTypes.SEQUENCE) {
sequence = ((ExpressionColumn) defaultExpr).sequence;
defaultExpr = null;
}
column.setDefaultExpression(defaultExpr);
column.setIdentity(sequence);
}
return column;
}
/**
* Reads and adds a table period definition to the table
*
* @param table a table
*/
PeriodDefinition readAndAddPeriod(Table table) {
PeriodDefinition period = readPeriod(table);
if (period == null) {
return null;
}
if (period.getPeriodType() == SchemaObject.PeriodType.PERIOD_SYSTEM) {
table.systemPeriod = period;
} else {
table.applicationPeriod = period;
}
return period;
}
PeriodDefinition readPeriod(Table table) {
int periodType = SchemaObject.PeriodType.PERIOD_NONE;
HsqlName periodName = null;
int position = getPosition();
readThis(Tokens.PERIOD);
if (token.tokenType != Tokens.FOR) {
rewind(position);
return null;
}
readThis(Tokens.FOR);
if (token.tokenType == Tokens.SYSTEM_TIME) {
periodType = SchemaObject.PeriodType.PERIOD_SYSTEM;
periodName =
database.nameManager.newHsqlName(table.getName().schema,
token.tokenString, false,
SchemaObject.PERIOD);
read();
} else {
periodType = SchemaObject.PeriodType.PERIOD_APPLICATION;
// always use strict naming
checkIsNonReservedIdentifier();
checkIsIrregularCharInIdentifier();
checkIsSimpleName();
periodName =
database.nameManager.newHsqlName(table.getName().schema,
token.tokenString,
isDelimitedIdentifier(),
SchemaObject.PERIOD);
read();
}
periodName.parent = table.getName();
OrderedHashSet set = readColumnNames(false);
if (set.size() != 2) {
throw Error.error(ErrorCode.X_42593);
}
PeriodDefinition period = new PeriodDefinition(periodName, periodType,
set);
if (period.getPeriodType() == SchemaObject.PeriodType.PERIOD_SYSTEM) {
if (table.systemPeriod != null) {
throw Error.error(ErrorCode.X_42581); // unexpected token (for now)
}
} else {
if (table.applicationPeriod != null) {
throw Error.error(ErrorCode.X_42581); // unexpected token (for now)
}
}
return period;
}
/**
* Reads and adds a table constraint definition to the list
*
* @param schemaObject table or domain
* @param constraintList list of constraints
*/
void readConstraint(SchemaObject schemaObject,
HsqlArrayList constraintList) {
HsqlName constName = null;
if (token.tokenType == Tokens.CONSTRAINT) {
read();
constName =
readNewDependentSchemaObjectName(schemaObject.getName(),
SchemaObject.CONSTRAINT);
}
switch (token.tokenType) {
case Tokens.PRIMARY : {
if (schemaObject.getName().type != SchemaObject.TABLE) {
throw unexpectedTokenRequire(Tokens.T_CHECK);
}
read();
readThis(Tokens.KEY);
Constraint mainConst;
mainConst = (Constraint) constraintList.get(0);
if (mainConst.getConstraintType()
== SchemaObject.ConstraintTypes.PRIMARY_KEY) {
if (!mainConst.isSimpleIdentityPK) {
throw Error.error(ErrorCode.X_42532);
}
}
if (constName == null) {
constName = database.nameManager.newAutoName("PK",
schemaObject.getSchemaName(),
schemaObject.getName(), SchemaObject.CONSTRAINT);
}
OrderedHashSet set = readColumnNames(false);
Constraint c =
new Constraint(constName, set,
SchemaObject.ConstraintTypes.PRIMARY_KEY);
constraintList.set(0, c);
break;
}
case Tokens.UNIQUE : {
if (schemaObject.getName().type != SchemaObject.TABLE) {
throw unexpectedTokenRequire(Tokens.T_CHECK);
}
read();
if (database.sqlSyntaxMys) {
if (!readIfThis(Tokens.INDEX)) {
readIfThis(Tokens.KEY);
}
}
OrderedHashSet set = readColumnNames(false);
if (constName == null) {
constName = database.nameManager.newAutoName("CT",
schemaObject.getSchemaName(),
schemaObject.getName(), SchemaObject.CONSTRAINT);
}
Constraint c =
new Constraint(constName, set,
SchemaObject.ConstraintTypes.UNIQUE);
constraintList.add(c);
break;
}
case Tokens.FOREIGN : {
if (schemaObject.getName().type != SchemaObject.TABLE) {
throw unexpectedTokenRequire(Tokens.T_CHECK);
}
read();
readThis(Tokens.KEY);
OrderedHashSet set = readColumnNames(false);
Constraint c = readFKReferences((Table) schemaObject,
constName, set);
constraintList.add(c);
break;
}
case Tokens.CHECK : {
read();
if (constName == null) {
constName = database.nameManager.newAutoName("CT",
schemaObject.getSchemaName(),
schemaObject.getName(), SchemaObject.CONSTRAINT);
}
Constraint c =
new Constraint(constName, null,
SchemaObject.ConstraintTypes.CHECK);
readCheckConstraintCondition(c);
constraintList.add(c);
break;
}
default : {
if (constName != null) {
throw unexpectedToken();
}
}
}
}
/**
* Reads column constraints
*/
void readColumnConstraints(Table table, ColumnSchema column,
HsqlArrayList constraintList) {
boolean end = false;
boolean hasNotNullConstraint = false;
boolean hasNullNoiseWord = false;
boolean hasPrimaryKey = false;
if (column.getDataType().isTimestampType()) {
if (token.tokenType == Tokens.ON) {
int position = getPosition();
FunctionSQL function;
try {
read();
readThis(Tokens.UPDATE);
if (readIfThis(Tokens.CURRENT_TIMESTAMP)) {
function = FunctionSQL.newSQLFunction(
Tokens.T_CURRENT_TIMESTAMP, compileContext);
} else {
readThis(Tokens.LOCALTIMESTAMP);
function =
FunctionSQL.newSQLFunction(Tokens.T_LOCALTIMESTAMP,
compileContext);
}
function.resolveTypes(session, null);
column.setUpdateExpression(function);
} catch (Exception e) {
rewind(position);
}
}
}
while (true) {
HsqlName constName = null;
if (token.tokenType == Tokens.CONSTRAINT) {
read();
constName = readNewDependentSchemaObjectName(table.getName(),
SchemaObject.CONSTRAINT);
}
switch (token.tokenType) {
case Tokens.PRIMARY : {
if (hasNullNoiseWord || hasPrimaryKey) {
throw unexpectedToken();
}
read();
readThis(Tokens.KEY);
Constraint existingConst =
(Constraint) constraintList.get(0);
if (existingConst.getConstraintType()
== SchemaObject.ConstraintTypes.PRIMARY_KEY) {
throw Error.error(ErrorCode.X_42532);
}
OrderedHashSet set = new OrderedHashSet();
set.add(column.getName().name);
if (constName == null) {
constName = database.nameManager.newAutoName("PK",
table.getSchemaName(), table.getName(),
SchemaObject.CONSTRAINT);
}
Constraint c = new Constraint(
constName, set,
SchemaObject.ConstraintTypes.PRIMARY_KEY);
constraintList.set(0, c);
column.setPrimaryKey(true);
hasPrimaryKey = true;
break;
}
case Tokens.UNIQUE : {
read();
OrderedHashSet set = new OrderedHashSet();
set.add(column.getName().name);
if (constName == null) {
constName = database.nameManager.newAutoName("CT",
table.getSchemaName(), table.getName(),
SchemaObject.CONSTRAINT);
}
Constraint c =
new Constraint(constName, set,
SchemaObject.ConstraintTypes.UNIQUE);
constraintList.add(c);
break;
}
case Tokens.FOREIGN : {
read();
readThis(Tokens.KEY);
}
// fall through
case Tokens.REFERENCES : {
OrderedHashSet set = new OrderedHashSet();
set.add(column.getName().name);
Constraint c = readFKReferences(table, constName, set);
constraintList.add(c);
break;
}
case Tokens.CHECK : {
read();
if (constName == null) {
constName = database.nameManager.newAutoName("CT",
table.getSchemaName(), table.getName(),
SchemaObject.CONSTRAINT);
}
Constraint c =
new Constraint(constName, null,
SchemaObject.ConstraintTypes.CHECK);
readCheckConstraintCondition(c);
OrderedHashSet set = c.getCheckColumnExpressions();
for (int i = 0; i < set.size(); i++) {
ExpressionColumn e = (ExpressionColumn) set.get(i);
if (column.getName().name.equals(e.getColumnName())) {
if (e.getSchemaName() != null
&& !e.getSchemaName().equals(
table.getSchemaName().name)) {
throw Error.error(ErrorCode.X_42505);
}
} else {
throw Error.error(ErrorCode.X_42501);
}
}
constraintList.add(c);
break;
}
case Tokens.NOT : {
if (hasNotNullConstraint || hasNullNoiseWord) {
throw unexpectedToken();
}
read();
readThis(Tokens.NULL);
if (constName == null) {
constName = database.nameManager.newAutoName("CT",
table.getSchemaName(), table.getName(),
SchemaObject.CONSTRAINT);
}
Constraint c =
new Constraint(constName, null,
SchemaObject.ConstraintTypes.CHECK);
c.check = new ExpressionLogical(column);
constraintList.add(c);
hasNotNullConstraint = true;
break;
}
case Tokens.NULL : {
if (hasNotNullConstraint || hasNullNoiseWord
|| hasPrimaryKey) {
throw unexpectedToken();
}
if (constName != null) {
throw unexpectedToken();
}
read();
hasNullNoiseWord = true;
break;
}
default :
end = true;
break;
}
if (end) {
break;
}
}
}
/**
* Responsible for handling check constraints section of CREATE TABLE ...
*
* @param c check constraint
*/
void readCheckConstraintCondition(Constraint c) {
readThis(Tokens.OPENBRACKET);
isCheckOrTriggerCondition = true;
Expression condition = XreadBooleanValueExpression();
isCheckOrTriggerCondition = false;
readThis(Tokens.CLOSEBRACKET);
c.check = condition;
}
/**
* Reads a DEFAULT clause expression.
*/
/*
for datetime, the default must have the same fields
*/
Expression readDefaultClause(Type dataType) {
Expression e = null;
boolean minus = false;
if (token.tokenType == Tokens.NULL) {
read();
return new ExpressionValue(null, dataType);
}
if (dataType.isDateTimeType() || dataType.isIntervalType()) {
switch (token.tokenType) {
case Tokens.DATE :
case Tokens.TIME :
case Tokens.TIMESTAMP :
case Tokens.INTERVAL : {
e = readDateTimeIntervalLiteral(session);
if (e.dataType.typeCode != dataType.typeCode) {
// error message
throw unexpectedToken();
}
Object defaultValue = e.getValue(session, dataType);
return new ExpressionValue(defaultValue, dataType);
}
case Tokens.X_VALUE :
break;
default :
e = XreadDateTimeValueFunctionOrNull();
if (e == null) {
break;
}
e = XreadModifier(e);
break;
}
} else if (dataType.isNumberType()) {
if (database.sqlSyntaxPgs && token.tokenType == Tokens.NEXTVAL) {
return readNextvalFunction();
}
if (database.sqlDoubleNaN
&& dataType.typeCode == Types.SQL_DOUBLE) {
// special for NaN
e = XreadNumericValueExpression();
} else {
if (token.tokenType == Tokens.MINUS_OP) {
read();
minus = true;
}
}
} else if (dataType.isCharacterType()) {
switch (token.tokenType) {
case Tokens.USER :
case Tokens.CURRENT_USER :
case Tokens.CURRENT_ROLE :
case Tokens.SESSION_USER :
case Tokens.SYSTEM_USER :
case Tokens.CURRENT_CATALOG :
case Tokens.CURRENT_SCHEMA :
case Tokens.CURRENT_PATH :
FunctionSQL function =
FunctionSQL.newSQLFunction(token.tokenString,
compileContext);
e = readSQLFunction(function);
break;
default :
}
} else if (dataType.isBooleanType()) {
switch (token.tokenType) {
case Tokens.TRUE :
read();
return Expression.EXPR_TRUE;
case Tokens.FALSE :
read();
return Expression.EXPR_FALSE;
}
} else if (dataType.isBitType()) {
switch (token.tokenType) {
case Tokens.TRUE :
read();
return new ExpressionValue(BinaryData.singleBitOne,
dataType);
case Tokens.FALSE :
read();
return new ExpressionValue(BinaryData.singleBitZero,
dataType);
}
} else if (dataType.isArrayType()) {
e = readCollection(OpTypes.ARRAY);
if (e.nodes.length > 0) {
throw Error.parseError(ErrorCode.X_42562, null,
scanner.getLineNumber());
}
e.dataType = dataType;
return e;
}
if (e != null) {
e.resolveTypes(session, null);
if (!dataType.canBeAssignedFrom(e.getDataType())) {
throw Error.parseError(ErrorCode.X_42562, null,
scanner.getLineNumber());
}
return e;
}
boolean inParens = false;
if ((database.sqlSyntaxMss || database.sqlSyntaxPgs)
&& token.tokenType == Tokens.OPENBRACKET) {
read();
inParens = true;
}
if (token.tokenType == Tokens.X_VALUE) {
Object value = token.tokenValue;
Type valueType = token.dataType;
Type convertType = dataType;
if (dataType.typeCode == Types.SQL_CLOB) {
convertType = Type.getType(Types.SQL_VARCHAR, null,
database.collation,
dataType.precision, 0);
} else if (dataType.typeCode == Types.SQL_BLOB) {
convertType = Type.getType(Types.SQL_VARBINARY, null, null,
dataType.precision, 0);
}
if (minus) {
value = valueType.negate(value);
}
value = convertType.convertToType(session, value, valueType);
read();
if (inParens) {
readThis(Tokens.CLOSEBRACKET);
}
return new ExpressionValue(value, convertType);
}
if (database.sqlSyntaxOra || database.sqlSyntaxPgs) {
e = XreadSimpleValueExpressionPrimary();
if (e != null) {
if (e.getType() == OpTypes.ROW_SUBQUERY) {
TableDerived t = (TableDerived) e.getTable();
QuerySpecification qs =
(QuerySpecification) t.getQueryExpression();
qs.setReturningResult();
}
e.resolveColumnReferences(session, RangeGroup.emptyGroup, 0,
RangeGroup.emptyArray, null, true);
e.resolveTypes(session, null);
if (e.getType() == OpTypes.ROW_SUBQUERY) {
TableDerived t = (TableDerived) e.getTable();
QuerySpecification qs =
(QuerySpecification) t.getQueryExpression();
Table d = qs.getRangeVariables()[0].getTable();
if (d != session.database.schemaManager.dualTable
|| qs.exprColumns.length != 1) {
throw Error.error(ErrorCode.X_42565);
}
e = qs.exprColumns[0];
}
if (inParens) {
readThis(Tokens.CLOSEBRACKET);
}
return e;
}
}
if (database.sqlSyntaxDb2) {
Object value = null;
switch (dataType.typeComparisonGroup) {
case Types.SQL_VARCHAR :
value = "";
break;
case Types.SQL_VARBINARY :
value = BinaryData.zeroLengthBinary;
break;
case Types.SQL_NUMERIC :
value = Integer.valueOf(0);
break;
case Types.SQL_BOOLEAN :
value = Boolean.FALSE;
break;
case Types.SQL_CLOB :
value = "";
return new ExpressionValue(value,
Type.SQL_VARCHAR_DEFAULT);
case Types.SQL_BLOB :
value = BinaryData.zeroLengthBinary;
return new ExpressionValue(value,
Type.SQL_VARBINARY_DEFAULT);
case Types.TIME : {
FunctionSQL function =
FunctionSQL.newSQLFunction(Tokens.T_CURRENT_TIME,
compileContext);
function.resolveTypes(session, null);
return function;
}
case Types.DATE : {
FunctionSQL function =
FunctionSQL.newSQLFunction(Tokens.T_CURRENT_DATE,
compileContext);
function.resolveTypes(session, null);
return function;
}
case Types.TIMESTAMP : {
FunctionSQL function =
FunctionSQL.newSQLFunction(Tokens.T_CURRENT_TIMESTAMP,
compileContext);
function.resolveTypes(session, null);
return function;
}
}
value = dataType.convertToDefaultType(session, value);
return new ExpressionValue(value, dataType);
}
if (inParens) {
readThis(Tokens.CLOSEBRACKET);
}
throw unexpectedToken();
}
/**
* A comma after START WITH is accepted for 1.8.x compatibility
*/
void readSequenceOptions(NumberSequence sequence, boolean withType,
boolean isAlter, boolean allowComma) {
OrderedIntHashSet set = new OrderedIntHashSet();
while (true) {
boolean end = false;
if (set.contains(token.tokenType)) {
throw unexpectedToken();
}
switch (token.tokenType) {
case Tokens.AS : {
if (withType) {
set.add(token.tokenType);
read();
Type type = readTypeDefinition(false, true);
sequence.setDefaults(sequence.getName(), type);
break;
}
throw unexpectedToken();
}
case Tokens.START : {
set.add(token.tokenType);
read();
readThis(Tokens.WITH);
long value = readBigint();
sequence.setStartValueNoCheck(value);
if (allowComma) {
readIfThis(Tokens.COMMA);
}
break;
}
case Tokens.RESTART : {
if (!isAlter) {
end = true;
break;
}
set.add(token.tokenType);
read();
if (readIfThis(Tokens.WITH)) {
long value = readBigint();
sequence.setCurrentValueNoCheck(value);
} else {
sequence.setStartValueDefault();
}
break;
}
case Tokens.INCREMENT : {
set.add(token.tokenType);
read();
readThis(Tokens.BY);
long value = readBigint();
sequence.setIncrement(value);
break;
}
case Tokens.NO : {
read();
if (set.contains(token.tokenType)) {
throw unexpectedToken();
}
if (token.tokenType == Tokens.MAXVALUE) {
sequence.setDefaultMaxValue();
} else if (token.tokenType == Tokens.MINVALUE) {
sequence.setDefaultMinValue();
} else if (token.tokenType == Tokens.CYCLE) {
sequence.setCycle(false);
} else {
throw unexpectedToken();
}
set.add(token.tokenType);
read();
break;
}
case Tokens.MAXVALUE : {
set.add(token.tokenType);
read();
long value = readBigint();
sequence.setMaxValueNoCheck(value);
break;
}
case Tokens.MINVALUE : {
set.add(token.tokenType);
read();
long value = readBigint();
sequence.setMinValueNoCheck(value);
break;
}
case Tokens.CYCLE : {
set.add(token.tokenType);
read();
sequence.setCycle(true);
break;
}
default :
if ((database.sqlSyntaxOra || database.sqlSyntaxDb2)
&& isSimpleName()) {
if (token.tokenString.equals("NOCACHE")
|| token.tokenString.equals("NOCYCLE")
|| token.tokenString.equals("NOMAXVALUE")
|| token.tokenString.equals("NOMINVALUE")
|| token.tokenString.equals("NOORDER")
|| token.tokenString.equals("ORDER")) {
read();
break;
}
if (token.tokenString.equals("CACHE")) {
read();
readBigint();
break;
}
}
end = true;
break;
}
if (end) {
break;
}
}
sequence.checkValues();
}
private void readIndex(Table table, HsqlArrayList indexList) {
HsqlName indexHsqlName;
read();
indexHsqlName = readNewSchemaObjectName(SchemaObject.INDEX, true);
HsqlName tableSchema = table.getSchemaName();
indexHsqlName.schema = tableSchema;
indexHsqlName.parent = table.getName();
indexHsqlName.schema = table.getSchemaName();
if (readIfThis(Tokens.USING)) {
if ("BTREE".equals(token.tokenString)
|| "HASH".equals(token.tokenString)) {
read();
}
}
readThis(Tokens.ON);
int[] indexColumns = readColumnList(table, true);
Constraint c = new Constraint(indexHsqlName, table, indexColumns,
SchemaObject.INDEX);
indexList.add(c);
}
Boolean readIfNotExists() {
Boolean ifNot = Boolean.FALSE;
if (token.tokenType == Tokens.IF) {
int position = getPosition();
read();
if (token.tokenType == Tokens.NOT) {
read();
readThis(Tokens.EXISTS);
ifNot = Boolean.TRUE;
} else {
rewind(position);
ifNot = Boolean.FALSE;
}
}
return ifNot;
}
StatementSchema compileAlterTableAddPeriod(Table table) {
PeriodDefinition period = readPeriod(table);
if (period.getPeriodType() == SchemaObject.PeriodType.PERIOD_SYSTEM) {
checkPeriodColumnsAdd(table, period);
} else {
// application period not supported
setPeriodColumns(table, period);
throw Error.error(ErrorCode.X_0A501);
}
readThis(Tokens.ADD);
readIfThis(Tokens.COLUMN);
String nameString = (String) period.columnNames.get(0);
if (!token.tokenString.equals(nameString)) {
throw unexpectedToken();
}
HsqlArrayList list = new HsqlArrayList();
HsqlName hsqlName =
database.nameManager.newColumnHsqlName(table.getName(),
token.tokenString, isDelimitedIdentifier());
read();
ColumnSchema columnStart = readColumnDefinitionOrNull(table, hsqlName,
list);
if (columnStart == null) {
throw Error.error(ErrorCode.X_42000);
}
if (columnStart.getSystemPeriodType()
!= SchemaObject.PeriodSystemColumnType.PERIOD_ROW_START) {
throw Error.error(ErrorCode.X_42516, columnStart.getNameString());
}
readThis(Tokens.ADD);
readIfThis(Tokens.COLUMN);
checkIsSimpleName();
nameString = (String) period.columnNames.get(1);
if (!token.tokenString.equals(nameString)) {
throw unexpectedToken();
}
hsqlName = database.nameManager.newColumnHsqlName(table.getName(),
token.tokenString, isDelimitedIdentifier());
read();
ColumnSchema columnEnd = readColumnDefinitionOrNull(table, hsqlName,
list);
if (columnEnd == null) {
throw Error.error(ErrorCode.X_42000);
}
if (columnEnd.getSystemPeriodType()
!= SchemaObject.PeriodSystemColumnType.PERIOD_ROW_END) {
throw Error.error(ErrorCode.X_42516, columnEnd.getNameString());
}
period.startColumn = columnStart;
period.endColumn = columnEnd;
String sql = getLastPart();
Object[] args = new Object[] {
table, period
};
HsqlName[] writeLockNames =
database.schemaManager.getCatalogAndBaseTableNames(
table.getName());
return new StatementSchema(sql, StatementTypes.ADD_TABLE_PERIOD, args,
null, writeLockNames);
}
StatementSchema compileAlterTableDropPeriod(Table table) {
if (readIfThis(Tokens.SYSTEM_TIME)) {
//
} else {
// application period not supported
throw Error.error(ErrorCode.X_0A501);
}
PeriodDefinition period = table.systemPeriod;
if (period == null) {
throw Error.error(ErrorCode.X_42517);
}
if (table.isSystemVersioned) {
throw Error.error(ErrorCode.X_42518);
}
Boolean cascade = readIfThis(Tokens.CASCADE);
String sql = getLastPart();
Object[] args = new Object[] {
table, period, cascade
};
HsqlName[] writeLockNames =
database.schemaManager.getCatalogAndBaseTableNames(
table.getName());
return new StatementSchema(sql, StatementTypes.DROP_TABLE_PERIOD,
args, null, writeLockNames);
}
StatementSchema compileAlterTableAddVersioning(Table table) {
PeriodDefinition period = table.systemPeriod;
if (period == null) {
throw Error.error(ErrorCode.X_42518);
}
String sql = getLastPart();
Object[] args = new Object[]{ table };
HsqlName[] writeLockNames =
database.schemaManager.getCatalogAndBaseTableNames(
table.getName());
return new StatementSchema(sql,
StatementTypes.ADD_TABLE_SYSTEM_VERSIONING,
args, null, writeLockNames);
}
StatementSchema compileAlterTableDropVersioning(Table table) {
if (!table.isSystemVersioned) {
throw Error.error(ErrorCode.X_42518);
}
Boolean cascade = readIfThis(Tokens.CASCADE);
String sql = getLastPart();
Object[] args = new Object[] {
table, cascade
};
HsqlName[] writeLockNames =
database.schemaManager.getCatalogAndBaseTableNames(
table.getName());
return new StatementSchema(sql,
StatementTypes.DROP_TABLE_SYSTEM_VERSIONING,
args, null, writeLockNames);
}
}