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


package org.hsqldb;

import java.lang.reflect.Method;

import org.hsqldb.HsqlNameManager.HsqlName;
import org.hsqldb.error.Error;
import org.hsqldb.error.ErrorCode;
import org.hsqldb.index.Index;
import org.hsqldb.lib.ArrayUtil;
import org.hsqldb.lib.HsqlArrayList;
import org.hsqldb.lib.HsqlList;
import org.hsqldb.lib.OrderedHashSet;
import org.hsqldb.lib.OrderedIntHashSet;
import org.hsqldb.map.ValuePool;
import org.hsqldb.rights.Grantee;
import org.hsqldb.rights.GranteeManager;
import org.hsqldb.rights.Right;
import org.hsqldb.rights.User;
import org.hsqldb.types.Charset;
import org.hsqldb.types.Collation;
import org.hsqldb.types.Type;
import org.hsqldb.types.UserTypeModifier;

Parser for DDL statements
Author:Fred Toussi (fredt@users dot sourceforge.net)
Version:2.5.0
Since:1.9.0
/** * Parser for DDL statements * * @author Fred Toussi (fredt@users dot sourceforge.net) * @version 2.5.0 * @since 1.9.0 */
public class ParserDDL extends ParserRoutine { static final int[] schemaCommands = new int[] { Tokens.CREATE, Tokens.GRANT }; static final short[] startStatementTokens = new short[] { Tokens.CREATE, Tokens.GRANT, Tokens.ALTER, Tokens.DROP }; static final short[] startStatementTokensSchema = new short[] { Tokens.CREATE, Tokens.GRANT, }; ParserDDL(Session session, Scanner scanner) { super(session, scanner); } void reset(Session session, String sql) { super.reset(session, sql); } StatementSchema compileCreate() { int tableType; boolean isTable = false; boolean isOrReplace = false; read(); switch (token.tokenType) { case Tokens.GLOBAL : read(); readThis(Tokens.TEMPORARY); readIfThis(Tokens.MEMORY); readThis(Tokens.TABLE); isTable = true; tableType = TableBase.TEMP_TABLE; break; case Tokens.TEMP : read(); readThis(Tokens.TABLE); isTable = true; tableType = TableBase.TEMP_TABLE; break; case Tokens.TEMPORARY : read(); readThis(Tokens.TABLE); isTable = true; tableType = TableBase.TEMP_TABLE; break; case Tokens.MEMORY : read(); readThis(Tokens.TABLE); isTable = true; tableType = TableBase.MEMORY_TABLE; break; case Tokens.CACHED : read(); readThis(Tokens.TABLE); isTable = true; tableType = TableBase.CACHED_TABLE; break; case Tokens.TEXT : read(); readThis(Tokens.TABLE); isTable = true; tableType = TableBase.TEXT_TABLE; break; case Tokens.TABLE : read(); isTable = true; tableType = database.schemaManager.getDefaultTableType(); break; default : tableType = TableBase.MEMORY_TABLE; } if (isTable) { return compileCreateTable(tableType); } if (database.sqlSyntaxOra) { if (token.tokenType == Tokens.OR) { read(); readThis(Tokens.REPLACE); switch (token.tokenType) { case Tokens.FUNCTION : case Tokens.PROCEDURE : case Tokens.TRIGGER : case Tokens.TYPE : case Tokens.VIEW : case Tokens.SYNONYM : break; default : throw unexpectedToken(Tokens.T_OR); } isOrReplace = true; } } switch (token.tokenType) { // other objects case Tokens.ALIAS : return compileCreateAlias(); case Tokens.SEQUENCE : return compileCreateSequence(); case Tokens.SCHEMA : return compileCreateSchema(); case Tokens.TRIGGER : return compileCreateTrigger(isOrReplace); case Tokens.USER : return compileCreateUser(); case Tokens.ROLE : return compileCreateRole(); case Tokens.VIEW : return compileCreateView(false, isOrReplace); case Tokens.DOMAIN : return compileCreateDomain(); case Tokens.TYPE : return compileCreateType(isOrReplace); case Tokens.CHARACTER : return compileCreateCharacterSet(); case Tokens.COLLATION : return compileCreateCollation(); // index case Tokens.UNIQUE : read(); checkIsThis(Tokens.INDEX); return compileCreateIndex(true); case Tokens.INDEX : return compileCreateIndex(false); case Tokens.AGGREGATE : return compileCreateProcedureOrFunction(isOrReplace); case Tokens.FUNCTION : case Tokens.PROCEDURE : return compileCreateProcedureOrFunction(isOrReplace); case Tokens.SYNONYM : return compileCreateSynonym(isOrReplace); default : { throw unexpectedToken(); } } } Statement compileAlter() { read(); switch (token.tokenType) { case Tokens.INDEX : { read(); HsqlName name = readNewSchemaObjectName(SchemaObject.INDEX, true); name.setSchemaIfNull(session.getCurrentSchemaHsqlName()); if (token.tokenType == Tokens.RENAME) { read(); readThis(Tokens.TO); return compileRenameObject(name, SchemaObject.INDEX); } readThis(Tokens.AS); Index index = (Index) database.schemaManager.getSchemaObject(name); if (index == null) { throw Error.error(ErrorCode.X_42501); } Table table = (Table) database.schemaManager.getSchemaObject( index.getName().parent); int[] indexColumns = readColumnList(table, true); String sql = getLastPart(); Object[] args = new Object[] { table, indexColumns, index.getName() }; HsqlName[] writeLockNames = new HsqlName[] { database.getCatalogName(), table.getName() }; return new StatementSchema(sql, StatementTypes.ALTER_INDEX, args, null, writeLockNames); } case Tokens.SCHEMA : { read(); HsqlName name = readSchemaName(); readThis(Tokens.RENAME); readThis(Tokens.TO); return compileRenameSchema(name, SchemaObject.SCHEMA); } case Tokens.CATALOG : { read(); checkIsSimpleName(); String name = token.tokenString; checkValidCatalogName(name); read(); readThis(Tokens.RENAME); readThis(Tokens.TO); return compileRenameObject(database.getCatalogName(), SchemaObject.CATALOG); } case Tokens.SEQUENCE : { return compileAlterSequence(); } case Tokens.TABLE : { return compileAlterTable(); } case Tokens.USER : { return compileAlterUser(); } case Tokens.DOMAIN : { return compileAlterDomain(); } case Tokens.VIEW : { return compileAlterView(); } case Tokens.SESSION : { return compileAlterSession(); } case Tokens.SPECIFIC : { return compileAlterSpecificRoutine(); } case Tokens.ROUTINE : { return compileAlterRoutine(); } case Tokens.CONSTRAINT : { read(); Constraint constraint = (Constraint) readSchemaObjectName(SchemaObject.CONSTRAINT); readThis(Tokens.RENAME); readThis(Tokens.TO); return compileRenameObject(constraint.getName(), SchemaObject.CONSTRAINT); } default : { throw unexpectedToken(); } } } Statement compileAlterSpecificRoutine() { readThis(Tokens.SPECIFIC); readThis(Tokens.ROUTINE); Routine routine = (Routine) readSchemaObjectName(SchemaObject.SPECIFIC_ROUTINE); switch (token.tokenType) { case Tokens.RENAME : { read(); readThis(Tokens.TO); return compileRenameObject(routine.getSpecificName(), SchemaObject.SPECIFIC_ROUTINE); } } return compileAlterSpecificRoutine(routine); } Statement compileAlterRoutine() { readThis(Tokens.ROUTINE); RoutineSchema routine = (RoutineSchema) readSchemaObjectName(SchemaObject.ROUTINE); readThis(Tokens.RENAME); readThis(Tokens.TO); return compileRenameObject(routine.getName(), routine.getName().type); } Statement compileDrop() { int objectTokenType; int objectType; int statementType; boolean canCascade = false; boolean cascade = false; boolean useIfExists = false; boolean ifExists = false; SchemaObject object; HsqlName[] writeLockNames; read(); objectTokenType = token.tokenType; switch (objectTokenType) { case Tokens.INDEX : { read(); statementType = StatementTypes.DROP_INDEX; objectType = SchemaObject.INDEX; useIfExists = true; break; } case Tokens.ASSERTION : { read(); statementType = StatementTypes.DROP_ASSERTION; objectType = SchemaObject.ASSERTION; canCascade = true; break; } case Tokens.SPECIFIC : { read(); switch (token.tokenType) { case Tokens.ROUTINE : case Tokens.PROCEDURE : case Tokens.FUNCTION : read(); break; default : throw unexpectedToken(); } statementType = StatementTypes.DROP_ROUTINE; objectType = SchemaObject.SPECIFIC_ROUTINE; canCascade = true; useIfExists = true; break; } case Tokens.PROCEDURE : { read(); statementType = StatementTypes.DROP_ROUTINE; objectType = SchemaObject.PROCEDURE; canCascade = true; useIfExists = true; break; } case Tokens.FUNCTION : { read(); statementType = StatementTypes.DROP_ROUTINE; objectType = SchemaObject.FUNCTION; canCascade = true; useIfExists = true; break; } case Tokens.SCHEMA : { read(); statementType = StatementTypes.DROP_SCHEMA; objectType = SchemaObject.SCHEMA; canCascade = true; useIfExists = true; break; } case Tokens.SEQUENCE : { read(); statementType = StatementTypes.DROP_SEQUENCE; objectType = SchemaObject.SEQUENCE; canCascade = true; useIfExists = true; break; } case Tokens.TRIGGER : { read(); statementType = StatementTypes.DROP_TRIGGER; objectType = SchemaObject.TRIGGER; canCascade = false; useIfExists = true; break; } case Tokens.USER : { read(); statementType = StatementTypes.DROP_USER; objectType = SchemaObject.GRANTEE; canCascade = true; break; } case Tokens.ROLE : { read(); statementType = StatementTypes.DROP_ROLE; objectType = SchemaObject.GRANTEE; canCascade = true; break; } case Tokens.DOMAIN : read(); statementType = StatementTypes.DROP_DOMAIN; objectType = SchemaObject.DOMAIN; canCascade = true; useIfExists = true; break; case Tokens.TYPE : read(); statementType = StatementTypes.DROP_TYPE; objectType = SchemaObject.TYPE; canCascade = true; useIfExists = true; break; case Tokens.CHARACTER : read(); readThis(Tokens.SET); statementType = StatementTypes.DROP_CHARACTER_SET; objectType = SchemaObject.CHARSET; canCascade = false; useIfExists = true; break; case Tokens.COLLATION : read(); statementType = StatementTypes.DROP_COLLATION; objectType = SchemaObject.COLLATION; canCascade = false; useIfExists = true; break; case Tokens.VIEW : read(); statementType = StatementTypes.DROP_VIEW; objectType = SchemaObject.VIEW; canCascade = true; useIfExists = true; break; case Tokens.TABLE : read(); statementType = StatementTypes.DROP_TABLE; objectType = SchemaObject.TABLE; canCascade = true; useIfExists = true; break; case Tokens.SYNONYM : read(); statementType = StatementTypes.DROP_REFERENCE; objectType = SchemaObject.REFERENCE; canCascade = false; useIfExists = true; break; default : throw unexpectedToken(); } if (useIfExists && token.tokenType == Tokens.IF) { int position = getPosition(); read(); if (token.tokenType == Tokens.EXISTS) { read(); ifExists = true; } else { rewind(position); } } checkIsIdentifier(); HsqlName name = null; switch (objectTokenType) { case Tokens.USER : { checkIsSimpleName(); checkDatabaseUpdateAuthorisation(); object = database.getUserManager().get(token.tokenString); read(); break; } case Tokens.ROLE : { checkIsSimpleName(); checkDatabaseUpdateAuthorisation(); object = database.getGranteeManager().getRole(token.tokenString); read(); break; } case Tokens.SCHEMA : { name = readNewSchemaName(); object = database.schemaManager.findSchema(name.name); break; } case Tokens.TABLE : { boolean isModule = token.namePrePrefix == null && (Tokens.T_MODULE.equals(token.namePrefix) || Tokens.T_SESSION.equals(token.namePrefix)); if (isModule) { name = readNewSchemaObjectName(objectType, false); if (!ifExists && token.tokenType == Tokens.IF) { read(); readThis(Tokens.EXISTS); ifExists = true; } Object[] args = new Object[] { name, Boolean.valueOf(ifExists) }; return new StatementSession(StatementTypes.DROP_TABLE, args); } } // fall through default : name = readNewSchemaObjectName(objectType, false); name.setSchemaIfNull(session.getCurrentSchemaHsqlName()); object = database.schemaManager.findSchemaObject(name.name, name.schema.name, name.type); } if (!ifExists && useIfExists && token.tokenType == Tokens.IF) { read(); readThis(Tokens.EXISTS); ifExists = true; } if (canCascade) { if (token.tokenType == Tokens.CASCADE) { cascade = true; read(); if (database.sqlSyntaxOra) { readIfThis(Tokens.CONSTRAINTS); } } else if (token.tokenType == Tokens.RESTRICT) { read(); } } if (object == null) { writeLockNames = null; } else { if (objectType == SchemaObject.SPECIFIC_ROUTINE) { // } else { name = object.getName(); } writeLockNames = database.schemaManager.getCatalogAndBaseTableNames(name); } String sql = getLastPart(); Object[] args = new Object[] { name, Integer.valueOf(objectType), Boolean.valueOf(cascade), Boolean.valueOf(ifExists) }; Statement cs = new StatementSchema(sql, statementType, args, null, writeLockNames); return cs; } Statement compileAlterTable() { read(); String tableName = token.tokenString; HsqlName schema = session.getSchemaHsqlName(token.namePrefix); checkSchemaUpdateAuthorisation(schema); Table t = database.schemaManager.getUserTable(tableName, schema.name); read(); switch (token.tokenType) { case Tokens.RENAME : { read(); if (database.sqlSyntaxPgs) { if (token.tokenType != Tokens.TO) { if (token.tokenType == Tokens.COLUMN) { read(); } checkIsIdentifier(); int columnIndex = t.getColumnIndex(token.tokenString); ColumnSchema column = t.getColumn(columnIndex); read(); readThis(Tokens.TO); return compileAlterColumnRename(t, column); } } readThis(Tokens.TO); return compileRenameObject(t.getName(), SchemaObject.TABLE); } case Tokens.ADD : { read(); HsqlName cname = null; Boolean ifNotExists = Boolean.FALSE; if (token.tokenType == Tokens.CONSTRAINT) { read(); ifNotExists = readIfNotExists(); cname = readNewDependentSchemaObjectName(t.getName(), SchemaObject.CONSTRAINT); } switch (token.tokenType) { case Tokens.FOREIGN : read(); readThis(Tokens.KEY); return compileAlterTableAddForeignKeyConstraint(t, cname, ifNotExists); case Tokens.UNIQUE : read(); if (database.sqlSyntaxMys) { if (!readIfThis(Tokens.INDEX)) { readIfThis(Tokens.KEY); } } return compileAlterTableAddUniqueConstraint(t, cname, ifNotExists); case Tokens.CHECK : read(); return compileAlterTableAddCheckConstraint(t, cname, ifNotExists); case Tokens.PRIMARY : read(); readThis(Tokens.KEY); return compileAlterTableAddPrimaryKey(t, cname, ifNotExists); case Tokens.PERIOD : if (cname != null) { throw unexpectedToken(); } return compileAlterTableAddPeriod(t); case Tokens.SYSTEM : if (cname != null) { throw unexpectedToken(); } read(); readThis(Tokens.VERSIONING); return compileAlterTableAddVersioning(t); case Tokens.COLUMN : if (cname != null) { throw unexpectedToken(); } read(); checkIsSimpleName(); return compileAlterTableAddColumn(t); default : if (cname != null) { throw unexpectedToken(); } checkIsSimpleName(); return compileAlterTableAddColumn(t); } } case Tokens.DROP : { read(); switch (token.tokenType) { case Tokens.PRIMARY : { read(); readThis(Tokens.KEY); return compileAlterTableDropPrimaryKey(t); } case Tokens.CONSTRAINT : { read(); return compileAlterTableDropConstraint(t); } case Tokens.PERIOD : read(); readThis(Tokens.FOR); return compileAlterTableDropPeriod(t); case Tokens.SYSTEM : read(); readThis(Tokens.VERSIONING); return compileAlterTableDropVersioning(t); case Tokens.COLUMN : read(); return compileAlterTableDropColumn(t); default : return compileAlterTableDropColumn(t); } } case Tokens.ALTER : { read(); if (token.tokenType == Tokens.COLUMN) { read(); } int columnIndex = t.getColumnIndex(token.tokenString); ColumnSchema column = t.getColumn(columnIndex); read(); return compileAlterColumn(t, column, columnIndex); } default : { throw unexpectedToken(); } } } private Statement compileAlterTableDropConstraint(Table table) { boolean cascade = false; SchemaObject object = readSchemaObjectName(table.getSchemaName(), SchemaObject.CONSTRAINT); if (token.tokenType == Tokens.RESTRICT) { read(); } else if (token.tokenType == Tokens.CASCADE) { read(); cascade = true; } String sql = getLastPart(); Object[] args = new Object[] { object.getName(), ValuePool.getInt(SchemaObject.CONSTRAINT), Boolean.valueOf(cascade), Boolean.FALSE }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( table.getName()); HsqlName mainTableName = ((Constraint) object).getMainTableName(); if (mainTableName != null && mainTableName != table.getName()) { writeLockNames = (HsqlName[]) ArrayUtil.toAdjustedArray(writeLockNames, mainTableName, writeLockNames.length, 1); } Statement cs = new StatementSchema(sql, StatementTypes.DROP_CONSTRAINT, args, null, writeLockNames); return cs; } private Statement compileAlterTableDropPrimaryKey(Table table) { boolean cascade = false; if (token.tokenType == Tokens.RESTRICT) { read(); } else if (token.tokenType == Tokens.CASCADE) { read(); cascade = true; } if (!table.hasPrimaryKey()) { throw Error.error(ErrorCode.X_42501); } String sql = getLastPart(); SchemaObject object = table.getPrimaryConstraint(); Object[] args = new Object[] { object.getName(), ValuePool.getInt(SchemaObject.CONSTRAINT), Boolean.valueOf(cascade), Boolean.FALSE }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( table.getName()); Statement cs = new StatementSchema(sql, StatementTypes.DROP_CONSTRAINT, args, null, writeLockNames); return cs; } StatementSession compileDeclareLocalTableOrNull() { int position = getPosition(); try { readThis(Tokens.DECLARE); readThis(Tokens.LOCAL); readThis(Tokens.TEMPORARY); readThis(Tokens.TABLE); } catch (HsqlException e) { lastError = e; // may be cursor rewind(position); return null; } if (token.namePrePrefix == null && (token.namePrefix == null || Tokens.T_MODULE.equals(token.namePrefix) || Tokens.T_SESSION.equals(token.namePrefix))) { // valid name } else { throw unexpectedToken(); } boolean ifNot = readIfNotExists(); HsqlName name = readNewSchemaObjectName(SchemaObject.TABLE, false); name.schema = SqlInvariants.MODULE_HSQLNAME; Table table = new Table(database, name, TableBase.TEMP_TABLE); StatementSchema cs; if (token.tokenType == Tokens.AS) { cs = compileCreateTableAsSubqueryDefinition(table); } else { cs = compileCreateTableBody(table, ifNot); HsqlArrayList constraints = (HsqlArrayList) cs.arguments[1]; for (int i = 0; i < constraints.size(); i++) { Constraint c = (Constraint) constraints.get(i); if (c.getConstraintType() == SchemaObject.ConstraintTypes.FOREIGN_KEY) { throw unexpectedToken(Tokens.T_FOREIGN); } } } StatementSession ss = new StatementSession(StatementTypes.DECLARE_SESSION_TABLE, cs.arguments); return ss; } StatementSchema compileCreateView(boolean alter, boolean orReplace) { read(); Boolean ifNotExists = Boolean.FALSE; if (!alter) { ifNotExists = readIfNotExists(); } HsqlName name = readNewSchemaObjectName(SchemaObject.VIEW, true); name.setSchemaIfNull(session.getCurrentSchemaHsqlName()); checkSchemaUpdateAuthorisation(name.schema); HsqlName[] colList = null; if (token.tokenType == Tokens.OPENBRACKET) { try { colList = readColumnNames(name); } catch (HsqlException e) { if (session.isProcessingScript() && database.getProperties().isVersion18()) { while (token.tokenType != Tokens.AS) { read(); } } else { throw e; } } } readThis(Tokens.AS); startRecording(); QueryExpression queryExpression; try { isViewDefinition = true; queryExpression = XreadQueryExpression(); } catch (HsqlException e) { queryExpression = XreadJoinedTableAsView(); } finally { isViewDefinition = false; } Token[] tokenisedStatement = getRecordedStatement(); int check = SchemaObject.ViewCheckModes.CHECK_NONE; if (token.tokenType == Tokens.WITH) { read(); check = SchemaObject.ViewCheckModes.CHECK_CASCADE; if (readIfThis(Tokens.LOCAL)) { check = SchemaObject.ViewCheckModes.CHECK_LOCAL; } else { readIfThis(Tokens.CASCADED); } readThis(Tokens.CHECK); readThis(Tokens.OPTION); } View view = new View(database, name, colList, check); queryExpression.setView(view); queryExpression.resolve(session); view.setStatement(Token.getSQL(tokenisedStatement)); StatementQuery s = new StatementQuery(session, queryExpression, compileContext); String fullSQL = getLastPart(); Object[] args = new Object[] { view, ifNotExists }; int type = alter ? StatementTypes.ALTER_VIEW : StatementTypes.CREATE_VIEW; HsqlName[] writeLockNames = database.schemaManager.catalogNameArray; return new StatementSchema(fullSQL, type, args, s.readTableNames, writeLockNames); } StatementSchema compileCreateSequence() { read(); Boolean ifNotExists = readIfNotExists(); /* CREATE SEQUENCE <name> [AS {INTEGER | BIGINT}] [START WITH <value>] [INCREMENT BY <value>] */ HsqlName name = readNewSchemaObjectName(SchemaObject.SEQUENCE, false); NumberSequence sequence = new NumberSequence(name, Type.SQL_INTEGER); readSequenceOptions(sequence, true, false, false); String sql = getLastPart(); Object[] args = new Object[] { sequence, ifNotExists }; HsqlName[] writeLockNames = database.schemaManager.catalogNameArray; return new StatementSchema(sql, StatementTypes.CREATE_SEQUENCE, args, null, writeLockNames); } StatementSchema compileCreateDomain() { UserTypeModifier userTypeModifier = null; HsqlName name; read(); name = readNewSchemaObjectName(SchemaObject.DOMAIN, false); readIfThis(Tokens.AS); Type type = readTypeDefinition(true, false).duplicate(); Expression defaultClause = null; if (readIfThis(Tokens.DEFAULT)) { defaultClause = readDefaultClause(type); } userTypeModifier = new UserTypeModifier(name, SchemaObject.DOMAIN, type); userTypeModifier.setDefaultClause(defaultClause); type.userTypeModifier = userTypeModifier; HsqlArrayList tempConstraints = new HsqlArrayList(); compileContext.currentDomain = type; while (true) { boolean end = false; switch (token.tokenType) { case Tokens.CONSTRAINT : case Tokens.CHECK : readConstraint(type, tempConstraints); break; default : end = true; break; } if (end) { break; } } compileContext.currentDomain = null; for (int i = 0; i < tempConstraints.size(); i++) { Constraint c = (Constraint) tempConstraints.get(i); c.prepareDomainCheckConstraint(session); userTypeModifier.addConstraint(c); } String sql = getLastPart(); Object[] args = new Object[]{ type }; HsqlName[] writeLockNames = database.schemaManager.catalogNameArray; return new StatementSchema(sql, StatementTypes.CREATE_DOMAIN, args, null, writeLockNames); } StatementSchema compileCreateType(boolean orReplace) { read(); HsqlName name = readNewSchemaObjectName(SchemaObject.TYPE, false); readThis(Tokens.AS); Type type = readTypeDefinition(true, false).duplicate(); readIfThis(Tokens.FINAL); UserTypeModifier userTypeModifier = new UserTypeModifier(name, SchemaObject.TYPE, type); type.userTypeModifier = userTypeModifier; String sql = getLastPart(); Object[] args = new Object[]{ type }; HsqlName[] writeLockNames = database.schemaManager.catalogNameArray; return new StatementSchema(sql, StatementTypes.CREATE_TYPE, args, null, writeLockNames); } StatementSchema compileCreateCharacterSet() { read(); readThis(Tokens.SET); HsqlName name = readNewSchemaObjectName(SchemaObject.CHARSET, false); readIfThis(Tokens.AS); readThis(Tokens.GET); String schema = token.namePrefix; Charset source = (Charset) database.schemaManager.getCharacterSet(session, token.tokenString, schema); read(); if (token.tokenType == Tokens.COLLATION) { read(); readThis(Tokens.FROM); readThis(Tokens.DEFAULT); } Charset charset = new Charset(name, source.getName()); String sql = getLastPart(); Object[] args = new Object[]{ charset }; HsqlName[] writeLockNames = database.schemaManager.catalogNameArray; return new StatementSchema(sql, StatementTypes.CREATE_CHARACTER_SET, args, null, writeLockNames); } StatementSchema compileCreateCollation() { read(); HsqlName name = readNewSchemaObjectName(SchemaObject.COLLATION, false); name.setSchemaIfNull(session.getCurrentSchemaHsqlName()); readThis(Tokens.FOR); HsqlName charsetName = readNewSchemaObjectName(SchemaObject.CHARSET, false); readThis(Tokens.FROM); HsqlName sourceName = readNewSchemaObjectName(SchemaObject.COLLATION, false); Boolean padSpace = null; if (readIfThis(Tokens.NO)) { readThis(Tokens.PAD); padSpace = Boolean.FALSE; } else if (readIfThis(Tokens.PAD)) { readThis(Tokens.SPACE); padSpace = Boolean.TRUE; } String schemaName = charsetName.schema == null ? null : charsetName.schema .name; Charset charset = (Charset) database.schemaManager.getCharacterSet(session, charsetName.name, schemaName); if (charset == null) { throw Error.error(ErrorCode.X_42501, charsetName.getSchemaQualifiedStatementName()); } schemaName = sourceName.schema == null ? null : sourceName.schema.name; Collation source = database.schemaManager.getCollation(session, sourceName.name, schemaName); Collation collation = new Collation(name, source, charset, padSpace); String sql = getLastPart(); Object[] args = new Object[]{ collation }; HsqlName[] writeLockNames = database.schemaManager.catalogNameArray; return new StatementSchema(sql, StatementTypes.CREATE_COLLATION, args, null, writeLockNames); } StatementSchema compileCreateAlias() { HsqlName name = null; Routine[] routines = null; String alias; String methodFQN = null; if (!session.isProcessingScript()) { throw unsupportedFeature(); } read(); try { alias = token.tokenString; read(); readThis(Tokens.FOR); methodFQN = token.tokenString; read(); } catch (HsqlException e) { alias = null; } if (alias != null) { HsqlName schema = database.schemaManager.getDefaultSchemaHsqlName(); name = database.nameManager.newHsqlName(schema, alias, SchemaObject.FUNCTION); Method[] methods = Routine.getMethods(methodFQN); routines = Routine.newRoutines(session, methods); } String sql = getLastPart(); Object[] args = new Object[] { name, routines }; HsqlName[] writeLockNames = database.schemaManager.catalogNameArray; return new StatementSchema(sql, StatementTypes.CREATE_ALIAS, args, null, writeLockNames); } StatementSchema compileCreateIndex(boolean unique) { Table table; HsqlName indexHsqlName; read(); Boolean ifNotExists = readIfNotExists(); indexHsqlName = readNewSchemaObjectName(SchemaObject.INDEX, true); if (database.sqlSyntaxMys) { if (readIfThis(Tokens.USING)) { if (!readIfThis("HASH")) { readThis("BTREE"); } } } readThis(Tokens.ON); table = readTableName(); HsqlName tableSchema = table.getSchemaName(); indexHsqlName.setSchemaIfNull(tableSchema); indexHsqlName.parent = table.getName(); if (indexHsqlName.schema != tableSchema) { throw Error.error(ErrorCode.X_42505); } indexHsqlName.schema = table.getSchemaName(); int[] indexColumns = readColumnList(table, true); if (database.sqlSyntaxMys) { if (readIfThis(Tokens.USING)) { if (!readIfThis("HASH")) { readThis("BTREE"); } } if (readIfThis(Tokens.COMMENT)) { String comment = readQuotedString(); indexHsqlName.comment = comment; } } String sql = getLastPart(); Object[] args = new Object[] { table, indexColumns, indexHsqlName, Boolean.valueOf(unique), null, ifNotExists }; return new StatementSchema(sql, StatementTypes.CREATE_INDEX, args, null, new HsqlName[] { database.getCatalogName(), table.getName() }); } StatementSchema compileCreateSchema() { HsqlName schemaName = null; String authorisation = null; HsqlName characterSetName = null; read(); Boolean ifNotExists = readIfNotExists(); if (token.tokenType != Tokens.AUTHORIZATION) { schemaName = readNewSchemaName(); } if (token.tokenType == Tokens.AUTHORIZATION) { read(); checkIsSimpleName(); authorisation = token.tokenString; read(); if (schemaName == null) { Grantee owner = database.getGranteeManager().get(authorisation); if (owner == null) { throw Error.error(ErrorCode.X_28501, authorisation); } schemaName = database.nameManager.newHsqlName(owner.getName().name, isDelimitedIdentifier(), SchemaObject.SCHEMA); SqlInvariants.checkSchemaNameNotSystem(token.tokenString); } } if (SqlInvariants.PUBLIC_ROLE_NAME.equals(authorisation)) { throw Error.error(ErrorCode.X_28502, authorisation); } Grantee owner = authorisation == null ? session.getGrantee() : database.getGranteeManager() .get(authorisation); if (owner == null) { throw Error.error(ErrorCode.X_28501, authorisation); } if (!session.getGrantee().isSchemaCreator()) { throw Error.error(ErrorCode.X_0L501, session.getGrantee().getName().getNameString()); } if (owner instanceof User && ((User) owner).isExternalOnly) { throw Error.error(ErrorCode.X_0L000, session.getGrantee().getName().getNameString()); } if (database.schemaManager.schemaExists(schemaName.name)) { if (session.isProcessingScript() && SqlInvariants.PUBLIC_SCHEMA.equals(schemaName.name)) {} else { if (!ifNotExists.booleanValue()) { throw Error.error(ErrorCode.X_42504, schemaName.name); } } } if (schemaName.name.equals(SqlInvariants.LOBS_SCHEMA)) { schemaName = SqlInvariants.LOBS_SCHEMA_HSQLNAME; owner = schemaName.owner; } if (readIfThis(Tokens.DEFAULT)) { readThis(Tokens.CHARACTER); readThis(Tokens.SET); characterSetName = readNewSchemaObjectName(SchemaObject.CHARSET, false); } String sql = getLastPart(); Object[] args = new Object[] { schemaName, owner, ifNotExists }; HsqlName[] writeLockNames = database.schemaManager.catalogNameArray; StatementSchema cs = new StatementSchema(sql, StatementTypes.CREATE_SCHEMA, args, null, writeLockNames); cs.setSchemaHsqlName(schemaName); HsqlArrayList list = new HsqlArrayList(); list.add(cs); getCompiledStatementBody(list); StatementSchema[] array = new StatementSchema[list.size()]; list.toArray(array); boolean swapped; do { swapped = false; for (int i = 0; i < array.length - 1; i++) { if (array[i].order > array[i + 1].order) { StatementSchema temp = array[i + 1]; array[i + 1] = array[i]; array[i] = temp; swapped = true; } } } while (swapped); return new StatementSchemaDefinition(array); } void getCompiledStatementBody(HsqlList list) { int position; String sql; int statementType; for (boolean end = false; !end; ) { StatementSchema cs = null; position = getPosition(); switch (token.tokenType) { case Tokens.CREATE : read(); switch (token.tokenType) { // not in schema definition case Tokens.SCHEMA : case Tokens.USER : case Tokens.UNIQUE : throw unexpectedToken(); case Tokens.INDEX : statementType = StatementTypes.CREATE_INDEX; sql = getStatement(position, startStatementTokensSchema); cs = new StatementSchema(sql, statementType); break; case Tokens.SEQUENCE : cs = compileCreateSequence(); cs.sql = getLastPart(position); break; case Tokens.ROLE : cs = compileCreateRole(); cs.sql = getLastPart(position); break; case Tokens.DOMAIN : statementType = StatementTypes.CREATE_DOMAIN; sql = getStatement(position, startStatementTokensSchema); cs = new StatementSchema(sql, statementType); break; case Tokens.TYPE : cs = compileCreateType(false); cs.sql = getLastPart(position); break; case Tokens.CHARACTER : cs = compileCreateCharacterSet(); cs.sql = getLastPart(position); break; // no supported case Tokens.ASSERTION : throw unexpectedToken(); case Tokens.TABLE : case Tokens.MEMORY : case Tokens.CACHED : case Tokens.TEMP : case Tokens.GLOBAL : case Tokens.TEMPORARY : case Tokens.TEXT : statementType = StatementTypes.CREATE_TABLE; sql = getStatement(position, startStatementTokensSchema); cs = new StatementSchema(sql, statementType); break; case Tokens.TRIGGER : statementType = StatementTypes.CREATE_TRIGGER; sql = getStatement(position, startStatementTokensSchema); cs = new StatementSchema(sql, statementType); break; case Tokens.VIEW : statementType = StatementTypes.CREATE_VIEW; sql = getStatement(position, startStatementTokensSchema); cs = new StatementSchema(sql, statementType); break; case Tokens.FUNCTION : statementType = StatementTypes.CREATE_ROUTINE; sql = getStatementForRoutine( position, startStatementTokensSchema); cs = new StatementSchema(sql, statementType); break; case Tokens.PROCEDURE : statementType = StatementTypes.CREATE_ROUTINE; sql = getStatementForRoutine( position, startStatementTokensSchema); cs = new StatementSchema(sql, statementType); break; default : throw unexpectedToken(); } break; case Tokens.GRANT : cs = compileGrantOrRevoke(); cs.sql = getLastPart(position); break; case Tokens.SEMICOLON : read(); end = true; break; case Tokens.X_ENDPARSE : end = true; break; default : throw unexpectedToken(); } if (cs != null) { cs.isSchemaDefinition = true; list.add(cs); } } } StatementSchema compileCreateRole() { read(); HsqlName name = readNewUserIdentifier(); String sql = getLastPart(); Object[] args = new Object[]{ name }; HsqlName[] writeLockNames = database.schemaManager.catalogNameArray; return new StatementSchema(sql, StatementTypes.CREATE_ROLE, args, null, writeLockNames); } StatementSchema compileCreateUser() { HsqlName name; String password; Boolean admin = Boolean.FALSE; Boolean isDigest = Boolean.FALSE; Grantee grantor = session.getGrantee(); read(); name = readNewUserIdentifier(); readThis(Tokens.PASSWORD); if (readIfThis(Tokens.DIGEST)) { isDigest = Boolean.TRUE; } password = readPassword(); if (token.tokenType == Tokens.ADMIN) { read(); admin = Boolean.TRUE; } checkDatabaseUpdateAuthorisation(); String sql = getLastPart(); Object[] args = new Object[] { name, password, grantor, admin, isDigest }; HsqlName[] writeLockNames = database.schemaManager.catalogNameArray; return new StatementSchema(sql, StatementTypes.CREATE_USER, args, null, writeLockNames); } HsqlName readNewUserIdentifier() { checkIsSimpleName(); String tokenS = token.tokenString; boolean isQuoted = isDelimitedIdentifier(); if (tokenS.equalsIgnoreCase("SA")) { tokenS = "SA"; isQuoted = false; } HsqlName name = database.nameManager.newHsqlName(tokenS, isQuoted, SchemaObject.GRANTEE); read(); return name; } String readPassword() { String tokenS = token.tokenString; if (isUndelimitedSimpleName() || isDelimitedSimpleName()) { read(); } else { readQuotedString(); } return tokenS; } StatementSchema compileCreateSynonym(boolean isOrReplace) { HsqlName synonymHsqlName; HsqlName targetHsqlName; read(); synonymHsqlName = readNewSchemaObjectName(SchemaObject.REFERENCE, true); readThis(Tokens.FOR); targetHsqlName = readNewSchemaObjectName(SchemaObject.REFERENCE, true); String sql = getLastPart(); Object[] args = new Object[] { synonymHsqlName, targetHsqlName }; return new StatementSchema(sql, StatementTypes.CREATE_REFERENCE, args, null, new HsqlName[]{ database.getCatalogName() }); } Statement compileRenameObject(HsqlName name, int type) { HsqlName newName = readNewSchemaObjectName(type, true); String sql = getLastPart(); switch (type) { case SchemaObject.CATALOG : break; case SchemaObject.SCHEMA : checkSchemaUpdateAuthorisation(session, name); break; default : name.setSchemaIfNull(session.getCurrentSchemaHsqlName()); checkSchemaUpdateAuthorisation(session, name.schema); } Object[] args = new Object[] { name, newName }; HsqlName[] writeLockNames = database.schemaManager.getCatalogNameArray(); return new StatementSchema(sql, StatementTypes.RENAME_OBJECT, args, null, writeLockNames); } Statement compileAlterTableAddUniqueConstraint(Table table, HsqlName name, Boolean ifNotExists) { if (name == null) { name = database.nameManager.newAutoName("CT", table.getSchemaName(), table.getName(), SchemaObject.CONSTRAINT); } int[] cols = readColumnList(table, false); HsqlName indexName = session.database.nameManager.newConstraintIndexName( table.getName(), name, session.database.sqlSysIndexNames); Index index = table.createIndexStructure(indexName, cols, null, null, false, true, true, false); Constraint constraint = new Constraint(name, table, index, SchemaObject.ConstraintTypes.UNIQUE); String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ADD_CONSTRAINT, table, constraint, ifNotExists }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( table.getName()); return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); } Statement compileAlterTableAddForeignKeyConstraint(Table table, HsqlName name, Boolean ifNotExists) { if (name == null) { name = database.nameManager.newAutoName("FK", table.getSchemaName(), table.getName(), SchemaObject.CONSTRAINT); } OrderedHashSet set = readColumnNames(false); Constraint c = readFKReferences(table, name, set); HsqlName mainTableName = c.getMainTableName(); c.core.mainTable = database.schemaManager.getUserTable(mainTableName.name, mainTableName.schema.name); c.setColumnsIndexes(table); if (c.core.mainCols.length != c.core.refCols.length) { throw Error.error(ErrorCode.X_42593); } String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ADD_CONSTRAINT, table, c, ifNotExists }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( table.getName()); if (mainTableName != table.getName()) { writeLockNames = (HsqlName[]) ArrayUtil.toAdjustedArray(writeLockNames, mainTableName, writeLockNames.length, 1); } return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); } Statement compileAlterTableAddCheckConstraint(Table table, HsqlName name, Boolean ifNotExists) { Constraint check; if (name == null) { name = database.nameManager.newAutoName("CT", table.getSchemaName(), table.getName(), SchemaObject.CONSTRAINT); } check = new Constraint(name, null, SchemaObject.ConstraintTypes.CHECK); readCheckConstraintCondition(check); String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ADD_CONSTRAINT, table, check, ifNotExists }; HsqlName[] writeLockNames = new HsqlName[] { database.getCatalogName(), table.getName() }; return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); } Statement compileAlterTableAddColumn(Table table) { int colIndex = table.getColumnCount(); HsqlArrayList list = new HsqlArrayList(); Constraint constraint = new Constraint(null, null, SchemaObject.ConstraintTypes.TEMP); Boolean ifNotExists = readIfNotExists(); list.add(constraint); checkIsSimpleName(); checkIsSchemaObjectName(); HsqlName hsqlName = database.nameManager.newColumnHsqlName(table.getName(), token.tokenString, isDelimitedIdentifier()); read(); ColumnSchema column = readColumnDefinitionOrNull(table, hsqlName, list); if (column == null) { throw Error.error(ErrorCode.X_42000); } if (token.tokenType == Tokens.BEFORE) { read(); colIndex = table.getColumnIndex(token.tokenString); read(); } String sql = getLastPart(); Object[] args = new Object[] { Integer.valueOf(StatementTypes.ADD_COLUMN), table, column, Integer.valueOf(colIndex), list, ifNotExists }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( table.getName()); return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); } Statement compileAlterTableAddPrimaryKey(Table table, HsqlName name, Boolean ifNotExists) { if (name == null) { name = session.database.nameManager.newAutoName("PK", table.getSchemaName(), table.getName(), SchemaObject.CONSTRAINT); } OrderedHashSet set = readColumnNames(false); Constraint constraint = new Constraint(name, set, SchemaObject.ConstraintTypes.PRIMARY_KEY); constraint.setColumnsIndexes(table); String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ADD_CONSTRAINT, table, constraint, ifNotExists }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( table.getName()); return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); } Statement compileAlterTableDropColumn(Table table) { boolean cascade = false; checkIsSimpleName(); String colName = token.tokenString; read(); if (token.tokenType == Tokens.RESTRICT) { read(); } else if (token.tokenType == Tokens.CASCADE) { read(); cascade = true; } int colindex = table.getColumnIndex(colName); if (table.getColumnCount() == 1) { throw Error.error(ErrorCode.X_42591); } String sql = getLastPart(); Object[] args = new Object[] { table.getColumn(colindex).getName(), ValuePool.getInt(SchemaObject.COLUMN), Boolean.valueOf(cascade), Boolean.FALSE }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( table.getName()); return new StatementSchema(sql, StatementTypes.DROP_COLUMN, args, null, writeLockNames); } Statement compileAlterColumn(Table table, ColumnSchema column, int columnIndex) { HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( table.getName()); int position = getPosition(); switch (token.tokenType) { case Tokens.RENAME : { read(); readThis(Tokens.TO); return compileAlterColumnRename(table, column); } case Tokens.DROP : { read(); if (token.tokenType == Tokens.DEFAULT) { read(); String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ALTER_COLUMN_DROP_DEFAULT, table, column, Integer.valueOf(columnIndex) }; return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); } else if (token.tokenType == Tokens.EXPRESSION) { read(); String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ALTER_COLUMN_DROP_EXPRESSION, table, column, Integer.valueOf(columnIndex) }; return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); } else if (token.tokenType == Tokens.GENERATED || token.tokenType == Tokens.IDENTITY) { read(); String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ALTER_COLUMN_DROP_GENERATED, table, column, Integer.valueOf(columnIndex) }; return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); } else if (token.tokenType == Tokens.NOT) { read(); readThis(Tokens.NULL); String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ALTER_COLUMN_NULL, table, column, Boolean.TRUE }; return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); } else { throw unexpectedToken(); } } case Tokens.SET : { read(); switch (token.tokenType) { case Tokens.DATA : { read(); readThis(Tokens.TYPE); return compileAlterColumnDataType(table, column); } case Tokens.DEFAULT : { read(); return compileAlterColumnDefault(table, column, columnIndex); } case Tokens.NOT : { //ALTER TABLE .. ALTER COLUMN .. SET NOT NULL read(); readThis(Tokens.NULL); return compileAlterColumnSetNullability(table, column, false); } case Tokens.NULL : { read(); return compileAlterColumnSetNullability(table, column, true); } case Tokens.GENERATED : { return compileAlterColumnAddSequence(table, column, columnIndex); } default : rewind(position); read(); break; } break; } case Tokens.TYPE : { if (database.sqlSyntaxPgs) { read(); return compileAlterColumnDataType(table, column); } break; } case Tokens.GENERATED : return compileAlterColumnAddSequence(table, column, columnIndex); default : } if (token.tokenType == Tokens.SET || token.tokenType == Tokens.RESTART) { if (!column.isIdentity()) { throw Error.error(ErrorCode.X_42535); } return compileAlterColumnSequenceOptions(table, column, columnIndex); } else { return compileAlterColumnDataTypeIdentity(table, column); } }
Allows changes to type of column or addition / removal of an IDENTITY generator. IDENTITY is removed if it does not appear in new column definition Constraint definitions are not allowed
/** * Allows changes to type of column or addition / removal of an IDENTITY generator. * IDENTITY is removed if it does not appear in new column definition * Constraint definitions are not allowed */
private Statement compileAlterColumnDataTypeIdentity(Table table, ColumnSchema column) { if (column.isGenerated()) { throw Error.error(ErrorCode.X_42561); } NumberSequence sequence = column.getIdentitySequence(); Type type = column.getDataType(); if (token.tokenType == Tokens.IDENTITY) { read(); if (!type.isIntegralType()) { throw Error.error(ErrorCode.X_42561); } if (sequence == null) { sequence = new NumberSequence(null, type); } } else { type = readTypeDefinition(true, true); switch (token.tokenType) { case Tokens.IDENTITY : { if (!type.isIntegralType()) { throw Error.error(ErrorCode.X_42561); } read(); if (sequence == null) { sequence = new NumberSequence(null, type); } break; } case Tokens.GENERATED : { sequence = readSequence(column); break; } default : sequence = null; } } String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ALTER_COLUMN_TYPE_IDENTITY, table, column, type, sequence }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( table.getName()); return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); } private Statement compileAlterColumnDataType(Table table, ColumnSchema column) { if (column.isGenerated()) { throw Error.error(ErrorCode.X_42561); } Type type = readTypeDefinition(true, true); if (column.isIdentity()) { if (!type.isIntegralType()) { throw Error.error(ErrorCode.X_42561); } } String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ALTER_COLUMN_TYPE, table, column, type }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( table.getName()); return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); } private Statement compileAlterColumnSetNullability(Table table, ColumnSchema column, boolean nullable) { String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ALTER_COLUMN_NULL, table, column, Boolean.valueOf(nullable) }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( table.getName()); return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); } private Statement compileAlterColumnDefault(Table table, ColumnSchema column, int columnIndex) { //ALTER TABLE .. ALTER COLUMN .. SET DEFAULT Type type = column.getDataType(); Expression expr = readDefaultClause(type); String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ALTER_COLUMN_DEFAULT, table, column, Integer.valueOf(columnIndex), expr }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( table.getName()); return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); } Statement compileAlterSequence() { read(); HsqlName schema = session.getSchemaHsqlName(token.namePrefix); NumberSequence sequence = database.schemaManager.getSequence(token.tokenString, schema.name, true); read(); if (token.tokenType == Tokens.RENAME) { read(); readThis(Tokens.TO); return compileRenameObject(sequence.getName(), SchemaObject.SEQUENCE); } checkSchemaUpdateAuthorisation(session, sequence.getName().schema); NumberSequence copy = sequence.duplicate(); readSequenceOptions(copy, false, true, false); String sql = getLastPart(); Object[] args = new Object[] { sequence, copy }; HsqlName[] writeLockNames = database.schemaManager.getCatalogNameArray(); return new StatementSchema(sql, StatementTypes.ALTER_SEQUENCE, args, null, writeLockNames); } StatementSchema compileAlterColumnAddSequence(Table table, ColumnSchema column, int colIndex) { if (!column.getDataType().isIntegralType()) { throw Error.error(ErrorCode.X_42525); } if (column.isIdentity()) { throw Error.error(ErrorCode.X_42525); } NumberSequence sequence = readSequence(column); String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ALTER_COLUMN_SEQUENCE, table, column, Integer.valueOf(colIndex), sequence }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( table.getName()); return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); } NumberSequence readSequence(ColumnSchema column) { readThis(Tokens.GENERATED); NumberSequence sequence; sequence = new NumberSequence(null, column.getDataType()); boolean generatedAlways = false; if (token.tokenType == Tokens.BY) { read(); readThis(Tokens.DEFAULT); } else { readThis(Tokens.ALWAYS); generatedAlways = true; } readThis(Tokens.AS); readThis(Tokens.IDENTITY); sequence.setAlways(generatedAlways); if (token.tokenType == Tokens.OPENBRACKET) { read(); readSequenceOptions(sequence, false, false, false); readThis(Tokens.CLOSEBRACKET); } sequence.checkValues(); return sequence; } StatementSchema compileAlterColumnSequenceOptions(Table table, ColumnSchema column, int columnIndex) { OrderedIntHashSet set = new OrderedIntHashSet(); NumberSequence sequence = column.getIdentitySequence().duplicate(); while (true) { boolean end = false; switch (token.tokenType) { case Tokens.RESTART : { if (!set.add(token.tokenType)) { throw unexpectedToken(); } read(); if (readIfThis(Tokens.WITH)) { long value = readBigint(); sequence.setCurrentValueNoCheck(value); } else { sequence.reset(); } break; } case Tokens.SET : read(); switch (token.tokenType) { case Tokens.INCREMENT : { if (!set.add(token.tokenType)) { throw unexpectedToken(); } read(); readThis(Tokens.BY); long value = readBigint(); sequence.setIncrement(value); break; } case Tokens.NO : read(); 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(); } if (!set.add(token.tokenType)) { throw unexpectedToken(); } read(); break; case Tokens.MAXVALUE : { if (!set.add(token.tokenType)) { throw unexpectedToken(); } read(); long value = readBigint(); sequence.setMaxValueNoCheck(value); break; } case Tokens.MINVALUE : { if (!set.add(token.tokenType)) { throw unexpectedToken(); } read(); long value = readBigint(); sequence.setMinValueNoCheck(value); break; } case Tokens.CYCLE : if (!set.add(token.tokenType)) { throw unexpectedToken(); } read(); sequence.setCycle(true); break; default : throw unexpectedToken(); } break; default : end = true; break; } if (end) { break; } } sequence.checkValues(); String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ALTER_COLUMN_SEQUENCE, table, column, Integer.valueOf(columnIndex), sequence }; HsqlName[] writeLockNames = new HsqlName[] { database.getCatalogName(), table.getName() }; return new StatementSchema(sql, StatementTypes.ALTER_TABLE, args, null, writeLockNames); }
Responsible for handling tail of ALTER COLUMN ... RENAME ...
/** * Responsible for handling tail of ALTER COLUMN ... RENAME ... */
private Statement compileAlterColumnRename(Table table, ColumnSchema column) { checkIsSimpleName(); HsqlName name = readNewSchemaObjectName(SchemaObject.COLUMN, true); if (table.findColumn(name.name) > -1) { throw Error.error(ErrorCode.X_42504, name.name); } database.schemaManager.checkColumnIsReferenced(table.getName(), column.getName()); String sql = getLastPart(); Object[] args = new Object[] { column.getName(), name }; HsqlName[] writeLockNames = new HsqlName[] { database.getCatalogName(), table.getName() }; return new StatementSchema(sql, StatementTypes.RENAME_OBJECT, args, null, writeLockNames); } Statement compileRenameSchema(HsqlName name, int type) { HsqlName newName = readNewSchemaObjectName(type, true); String sql = getLastPart(); checkSchemaUpdateAuthorisation(session, name); Object[] args = new Object[] { name, newName }; HsqlName[] writeLockNames = database.schemaManager.getCatalogNameArray(); return new StatementSchema(sql, StatementTypes.RENAME_SCHEMA, args, null, writeLockNames); } Statement compileAlterUser() { read(); String password; User userObject; HsqlName userName = readNewUserIdentifier(); userObject = database.getUserManager().get(userName.name); if (userName.name.equals(Tokens.T_PUBLIC)) { throw Error.error(ErrorCode.X_42503); } if (userName.name.equals(SqlInvariants.SYSTEM_AUTHORIZATION_NAME)) { throw Error.error(ErrorCode.X_42503); } readThis(Tokens.SET); switch (token.tokenType) { case Tokens.LOCAL : { read(); Boolean mode = processTrueOrFalseObject(); Object[] args = new Object[] { userObject, mode }; return new StatementCommand(StatementTypes.SET_USER_LOCAL, args); } case Tokens.PASSWORD : { read(); boolean isDigest = false; if (readIfThis(Tokens.DIGEST)) { isDigest = Boolean.TRUE; } password = readPassword(); Object[] args = new Object[] { userObject, password, Boolean.valueOf(isDigest) }; Statement cs = new StatementCommand(StatementTypes.SET_USER_PASSWORD, args); String sql = userObject.getSetUserPasswordDigestSQL(password, isDigest); cs.setSQL(sql); return cs; } case Tokens.INITIAL : { read(); readThis(Tokens.SCHEMA); HsqlName schemaName; if (token.tokenType == Tokens.DEFAULT) { schemaName = null; } else { schemaName = database.schemaManager.getSchemaHsqlName( token.tokenString); } read(); Object[] args = new Object[] { userObject, schemaName }; return new StatementCommand( StatementTypes.SET_USER_INITIAL_SCHEMA, args); } default : { throw unexpectedToken(); } } } Statement compileAlterDomain() { read(); HsqlName schema = session.getSchemaHsqlName(token.namePrefix); checkSchemaUpdateAuthorisation(schema); Type domain = database.schemaManager.getDomain(token.tokenString, schema.name, true); read(); switch (token.tokenType) { case Tokens.RENAME : { read(); readThis(Tokens.TO); return compileRenameObject(domain.getName(), SchemaObject.DOMAIN); } case Tokens.DROP : { read(); if (token.tokenType == Tokens.DEFAULT) { read(); String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.DROP_DEFAULT, domain }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( domain.getName()); return new StatementSchema(sql, StatementTypes.ALTER_DOMAIN, args, null, writeLockNames); } else if (token.tokenType == Tokens.CONSTRAINT) { read(); checkIsSchemaObjectName(); HsqlName name = database.schemaManager.getSchemaObjectName( domain.getSchemaName(), token.tokenString, SchemaObject.CONSTRAINT, true); read(); String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.DROP_CONSTRAINT, domain, name }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( domain.getName()); return new StatementSchema(sql, StatementTypes.ALTER_DOMAIN, args, null, writeLockNames); } else { throw unexpectedToken(); } } case Tokens.SET : { read(); readThis(Tokens.DEFAULT); Expression e = readDefaultClause(domain); String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ADD_DEFAULT, domain, e }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( domain.getName()); return new StatementSchema(sql, StatementTypes.ALTER_DOMAIN, args, null, writeLockNames); } case Tokens.ADD : { read(); if (token.tokenType == Tokens.CONSTRAINT || token.tokenType == Tokens.CHECK) { HsqlArrayList tempConstraints = new HsqlArrayList(); compileContext.currentDomain = domain; readConstraint(domain, tempConstraints); compileContext.currentDomain = null; Constraint c = (Constraint) tempConstraints.get(0); String sql = getLastPart(); Object[] args = new Object[] { StatementTypes.ADD_CONSTRAINT, domain, c }; HsqlName[] writeLockNames = database.schemaManager.getCatalogAndBaseTableNames( domain.getName()); return new StatementSchema(sql, StatementTypes.ALTER_DOMAIN, args, null, writeLockNames); } } } throw unexpectedToken(); } private Statement compileAlterView() { int position = getPosition(); read(); String tableName = token.tokenString; HsqlName schema = session.getSchemaHsqlName(token.namePrefix); checkSchemaUpdateAuthorisation(schema); Table t = database.schemaManager.getUserTable(tableName, schema.name); read(); switch (token.tokenType) { case Tokens.RENAME : { read(); readThis(Tokens.TO); return compileRenameObject(t.getName(), SchemaObject.VIEW); } case Tokens.AS : { rewind(position); return compileCreateView(true, false); } } throw unexpectedToken(); } private boolean isGrantToken() { switch (token.tokenType) { case Tokens.ALL : case Tokens.INSERT : case Tokens.UPDATE : case Tokens.SELECT : case Tokens.DELETE : case Tokens.USAGE : case Tokens.EXECUTE : case Tokens.REFERENCES : return true; default : return false; } } StatementSchema compileGrantOrRevoke() { boolean grant = token.tokenType == Tokens.GRANT; read(); if (isGrantToken() || (!grant && (token.tokenType == Tokens.GRANT || token.tokenType == Tokens.HIERARCHY))) { return compileRightGrantOrRevoke(grant); } else { return compileRoleGrantOrRevoke(grant); } } private StatementSchema compileRightGrantOrRevoke(boolean grant) { OrderedHashSet granteeList = new OrderedHashSet(); Grantee grantor = null; Right right = null; HsqlName objectName = null; boolean isTable = false; boolean isUsage = false; boolean isExec = false; boolean isAll = false; boolean isGrantOption = false; boolean cascade = false; if (!grant) { if (token.tokenType == Tokens.GRANT) { read(); readThis(Tokens.OPTION); readThis(Tokens.FOR); isGrantOption = true; } else if (token.tokenType == Tokens.HIERARCHY) { throw unsupportedFeature(); /* read(); readThis(Token.OPTION); readThis(Token.FOR); */ } } // ALL means all the rights the grantor can grant if (token.tokenType == Tokens.ALL) { read(); if (token.tokenType == Tokens.PRIVILEGES) { read(); } right = Right.fullRights; isAll = true; } else { right = new Right(); boolean loop = true; while (loop) { checkIsUndelimitedIdentifier(); int rightType = GranteeManager.getCheckSingleRight(token.tokenString); int grantType = token.tokenType; OrderedHashSet columnSet = null; read(); switch (grantType) { case Tokens.REFERENCES : case Tokens.SELECT : case Tokens.INSERT : case Tokens.UPDATE : if (token.tokenType == Tokens.OPENBRACKET) { columnSet = readColumnNames(false); } if (right == null) { right = new Right(); } right.set(rightType, columnSet); isTable = true; break; case Tokens.TRIGGER : if (right == null) { right = new Right(); } right.set(rightType, null); isTable = true; break; case Tokens.DELETE : if (right == null) { right = new Right(); } right.set(rightType, null); isTable = true; break; case Tokens.USAGE : if (isTable) { throw unexpectedToken(); } right = Right.fullRights; isUsage = true; loop = false; continue; case Tokens.EXECUTE : if (isTable) { throw unexpectedToken(); } right = Right.fullRights; isExec = true; loop = false; continue; } if (token.tokenType == Tokens.COMMA) { read(); continue; } break; } } readThis(Tokens.ON); int objectType = 0; switch (token.tokenType) { case Tokens.CLASS : if (!isExec && !isAll) { throw unexpectedToken(); } read(); if (!isSimpleName() || !isDelimitedIdentifier()) { throw Error.error(ErrorCode.X_42569); } objectType = SchemaObject.FUNCTION; break; case Tokens.SPECIFIC : { if (!isExec && !isAll) { throw unexpectedToken(); } read(); switch (token.tokenType) { case Tokens.ROUTINE : case Tokens.PROCEDURE : case Tokens.FUNCTION : read(); break; default : throw unexpectedToken(); } objectType = SchemaObject.SPECIFIC_ROUTINE; break; } case Tokens.FUNCTION : if (!isExec && !isAll) { throw unexpectedToken(); } read(); objectType = SchemaObject.FUNCTION; break; case Tokens.PROCEDURE : if (!isExec && !isAll) { throw unexpectedToken(); } read(); objectType = SchemaObject.PROCEDURE; break; case Tokens.ROUTINE : if (!isExec && !isAll) { throw unexpectedToken(); } read(); objectType = SchemaObject.ROUTINE; break; case Tokens.TYPE : if (!isUsage && !isAll) { throw unexpectedToken(); } read(); objectType = SchemaObject.TYPE; break; case Tokens.DOMAIN : if (!isUsage && !isAll) { throw unexpectedToken(); } read(); objectType = SchemaObject.DOMAIN; break; case Tokens.SEQUENCE : if (!isUsage && !isAll) { throw unexpectedToken(); } read(); objectType = SchemaObject.SEQUENCE; break; case Tokens.CHARACTER : if (!isUsage && !isAll) { throw unexpectedToken(); } read(); readThis(Tokens.SET); objectType = SchemaObject.CHARSET; break; case Tokens.TABLE : default : if (!isTable && !isAll) { throw unexpectedToken(); } readIfThis(Tokens.TABLE); objectType = SchemaObject.TABLE; } objectName = readNewSchemaObjectName(objectType, false); ExpressionLogical filter = null; if (grant) { if (objectType == SchemaObject.TABLE) { filter = XreadFilterExpressionOrNull(); right.setFilterExpression(filter); } readThis(Tokens.TO); } else { readThis(Tokens.FROM); } while (true) { checkIsSimpleName(); granteeList.add(token.tokenString); read(); if (token.tokenType == Tokens.COMMA) { read(); } else { break; } } if (grant) { if (token.tokenType == Tokens.WITH) { read(); readThis(Tokens.GRANT); readThis(Tokens.OPTION); isGrantOption = true; } /** @todo - implement */ if (token.tokenType == Tokens.GRANTED) { read(); readThis(Tokens.BY); if (token.tokenType == Tokens.CURRENT_USER) { read(); // } else { readThis(Tokens.CURRENT_ROLE); if (session.getRole() == null) { throw Error.error(ErrorCode.X_0P000); } grantor = session.getRole(); } } } else { if (token.tokenType == Tokens.CASCADE) { cascade = true; read(); } else { readThis(Tokens.RESTRICT); } } String sql = getLastPart(); int type = grant ? StatementTypes.GRANT : StatementTypes.REVOKE; Object[] args = new Object[] { granteeList, objectName, right, grantor, Boolean.valueOf(cascade), Boolean.valueOf(isGrantOption), filter }; HsqlName[] writeLockNames = database.schemaManager.getCatalogNameArray(); StatementSchema cs = new StatementSchema(sql, type, args, null, writeLockNames); return cs; } private StatementSchema compileRoleGrantOrRevoke(boolean grant) { Grantee grantor = session.getGrantee(); OrderedHashSet roleList = new OrderedHashSet(); OrderedHashSet granteeList = new OrderedHashSet(); boolean cascade = false; if (!grant && token.tokenType == Tokens.ADMIN) { throw unsupportedFeature(); /* read(); readThis(Token.OPTION); readThis(Token.FOR); */ } while (true) { checkIsSimpleName(); roleList.add(token.tokenString); read(); if (token.tokenType == Tokens.COMMA) { read(); continue; } break; } if (grant) { readThis(Tokens.TO); } else { readThis(Tokens.FROM); } while (true) { checkIsSimpleName(); granteeList.add(token.tokenString); read(); if (token.tokenType == Tokens.COMMA) { read(); } else { break; } } if (grant) { if (token.tokenType == Tokens.WITH) { throw unsupportedFeature(); /* read(); readThis(Token.ADMIN); readThis(Token.OPTION); */ } } if (token.tokenType == Tokens.GRANTED) { read(); readThis(Tokens.BY); if (token.tokenType == Tokens.CURRENT_USER) { read(); // } else { readThis(Tokens.CURRENT_ROLE); if (session.getRole() == null) { throw Error.error(ErrorCode.X_0P000); } grantor = session.getRole(); } } if (!grant) { if (token.tokenType == Tokens.CASCADE) { cascade = true; read(); } else { readThis(Tokens.RESTRICT); } } String sql = getLastPart(); int type = grant ? StatementTypes.GRANT_ROLE : StatementTypes.REVOKE_ROLE; Object[] args = new Object[] { granteeList, roleList, grantor, Boolean.valueOf(cascade) }; HsqlName[] writeLockNames = database.schemaManager.getCatalogNameArray(); StatementSchema cs = new StatementSchema(sql, type, args, null, writeLockNames); return cs; } void checkDatabaseUpdateAuthorisation() { session.checkAdmin(); session.checkDDLWrite(); } void checkSchemaUpdateAuthorisation(Session session, HsqlName schema) { if (session.isProcessingLog()) { return; } if (SqlInvariants.isSystemSchemaName(schema.name)) { throw Error.error(ErrorCode.X_42503); } if (session.parser.isSchemaDefinition) { if (schema == session.getCurrentSchemaHsqlName()) { return; } throw Error.error(ErrorCode.X_42505, schema.name); } session.getGrantee().checkSchemaUpdateOrGrantRights(schema.name); session.checkDDLWrite(); } StatementSchema compileComment() { HsqlName name; int type; readThis(Tokens.COMMENT); readThis(Tokens.ON); switch (token.tokenType) { case Tokens.ROUTINE : case Tokens.TABLE : { type = token.tokenType == Tokens.ROUTINE ? SchemaObject.ROUTINE : SchemaObject.TABLE; read(); checkIsSchemaObjectName(); name = database.nameManager.newHsqlName(token.tokenString, token.isDelimitedIdentifier, type); if (token.namePrefix == null) { name.schema = session.getCurrentSchemaHsqlName(); } else { name.schema = database.nameManager.newHsqlName( token.namePrefix, token.isDelimitedPrefix, SchemaObject.SCHEMA); } read(); break; } case Tokens.COLUMN : { read(); checkIsSchemaObjectName(); name = database.nameManager.newHsqlName(token.tokenString, token.isDelimitedIdentifier, SchemaObject.COLUMN); if (token.namePrefix == null) { throw Error.error(ErrorCode.X_42501); } name.parent = database.nameManager.newHsqlName(token.namePrefix, token.isDelimitedPrefix, SchemaObject.TABLE); if (token.namePrePrefix == null) { name.parent.schema = session.getCurrentSchemaHsqlName(); } else { name.parent.schema = database.nameManager.newHsqlName( token.namePrePrefix, token.isDelimitedPrePrefix, SchemaObject.TABLE); } read(); break; } default : throw unexpectedToken(); } readThis(Tokens.IS); String comment = readQuotedString(); Object[] arguments = new Object[] { name, comment }; return new StatementSchema(null, StatementTypes.COMMENT, arguments, null, null); } Statement compileAlterSession() { read(); session.checkAdmin(); if (token.tokenType == Tokens.RESET) { read(); int action = token.tokenType; switch (token.tokenType) { case Tokens.ALL : read(); break; case Tokens.RESULT : read(); readThis(Tokens.SETS); break; case Tokens.TABLE : read(); readThis(Tokens.DATA); break; default : throw unexpectedTokenRequire(Tokens.T_ALL + ',' + Tokens.T_RESULT + ',' + Tokens.T_TABLE); } Object[] args = new Object[] { Long.valueOf(session.getId()), Integer.valueOf(action) }; return new StatementCommand(StatementTypes.ALTER_SESSION, args); } long sessionID = readBigint(); Session targetSession = database.sessionManager.getSession(sessionID); if (targetSession == null) { throw Error.error(ErrorCode.X_2E000); } int action = token.tokenType; switch (token.tokenType) { case Tokens.CLOSE : read(); break; case Tokens.RELEASE : read(); break; case Tokens.END : read(); readThis(Tokens.STATEMENT); break; default : throw unexpectedToken(); } Object[] args = new Object[] { Long.valueOf(sessionID), Integer.valueOf(action) }; return new StatementCommand(StatementTypes.ALTER_SESSION, args); }
Retrieves boolean value corresponding to the next token.
Throws:
Returns: true if next token is "TRUE"; false if next token is "FALSE"
/** * Retrieves boolean value corresponding to the next token. * * @return true if next token is "TRUE"; false if next token is "FALSE" * @throws HsqlException if the next token is neither "TRUE" or "FALSE" */
boolean processTrueOrFalse() { if (token.namePrefix != null) { throw unexpectedToken(); } if (token.tokenType == Tokens.TRUE) { read(); return true; } else if (token.tokenType == Tokens.FALSE) { read(); return false; } else { throw unexpectedToken(); } } Boolean processTrueOrFalseObject() { return Boolean.valueOf(processTrueOrFalse()); } }