alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  
, ...) * REFERENCE <other table> (, ...) [ON DELETE CASCADE] * * ALTER TABLE <name> ADD CONSTRAINT UNIQUE (, ...) * * @throws HsqlException */ private void processAlter() throws HsqlException { String token; session.checkAdmin(); session.checkDDLWrite(); session.setScripting(true); token = tokenizer.getSimpleToken(); switch (Token.get(token)) { case Token.INDEX : { processAlterIndex(); break; } case Token.SCHEMA : { processAlterSchema(); break; } case Token.SEQUENCE : { processAlterSequence(); break; } case Token.TABLE : { processAlterTable(); break; } case Token.USER : { processAlterUser(); break; } default : { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } } } /** * Handles ALTER TABLE DDL. * * @throws HsqlException */ private void processAlterTable() throws HsqlException { String tableName = tokenizer.getName(); String schema = session.getSchemaNameForWrite(tokenizer.getLongNameFirst()); Table t = database.schemaManager.getUserTable(session, tableName, schema); String token; if (t.isView()) { throw Trace.error(Trace.NOT_A_TABLE); } session.setScripting(true); token = tokenizer.getSimpleToken(); switch (Token.get(token)) { case Token.RENAME : { processAlterTableRename(t); return; } case Token.ADD : { HsqlName cname = null; if (tokenizer.isGetThis(Token.T_CONSTRAINT)) { token = tokenizer.getName(); String constraintSchema = tokenizer.getLongNameFirst(); if (constraintSchema != null) { constraintSchema = session.getSchemaNameForWrite( tokenizer.getLongNameFirst()); if (!t.getSchemaName().equals(constraintSchema)) { throw Trace.error( Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS, constraintSchema); } } cname = database.nameManager.newHsqlName(token, tokenizer.wasQuotedIdentifier()); } token = tokenizer.getString(); if (tokenizer.wasQuotedIdentifier() && tokenizer.wasSimpleName()) { tokenizer.back(); processAlterTableAddColumn(t); return; } if (!tokenizer.wasSimpleToken()) { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } switch (Token.get(token)) { case Token.FOREIGN : tokenizer.getThis(Token.T_KEY); processAlterTableAddForeignKeyConstraint(t, cname); return; case Token.UNIQUE : processAlterTableAddUniqueConstraint(t, cname); return; case Token.CHECK : processAlterTableAddCheckConstraint(t, cname); return; case Token.PRIMARY : tokenizer.getThis(Token.T_KEY); processAlterTableAddPrimaryKey(t, cname); return; default : if (cname != null) { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } tokenizer.back(); case Token.COLUMN : processAlterTableAddColumn(t); return; } } case Token.DROP : { token = tokenizer.getString(); if (tokenizer.wasQuotedIdentifier() && tokenizer.wasSimpleName()) { tokenizer.back(); processAlterTableDropColumn(t); return; } if (!tokenizer.wasSimpleToken()) { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } switch (Token.get(token)) { case Token.PRIMARY : tokenizer.getThis(Token.T_KEY); if (t.hasPrimaryKey()) { processAlterTableDropConstraint( t, t.getPrimaryConstraint().getName().name); } else { throw Trace.error(Trace.CONSTRAINT_NOT_FOUND, Trace.TABLE_HAS_NO_PRIMARY_KEY, new Object[] { "PRIMARY KEY", t.getName().name }); } return; case Token.CONSTRAINT : processAlterTableDropConstraint(t); return; default : tokenizer.back(); case Token.COLUMN : processAlterTableDropColumn(t); return; } } case Token.ALTER : { tokenizer.isGetThis(Token.T_COLUMN); processAlterColumn(t); return; } default : { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } } } /** * Handles ALTER COLUMN * * @param t table * @throws HsqlException */ private void processAlterColumn(Table t) throws HsqlException { String columnName = tokenizer.getSimpleName(); int columnIndex = t.getColumnNr(columnName); Column column = t.getColumn(columnIndex); String token = tokenizer.getSimpleToken(); switch (Token.get(token)) { case Token.RENAME : { tokenizer.getThis(Token.T_TO); processAlterColumnRename(t, column); return; } case Token.DROP : { tokenizer.getThis(Token.T_DEFAULT); TableWorks tw = new TableWorks(session, t); tw.setColDefaultExpression(columnIndex, null); return; } case Token.SET : { //4-8-2005 MarcH and HuugO ALTER TABLE <tablename> ALTER COLUMN SET [NOT] NULL support added token = tokenizer.getSimpleToken(); if (token.equals(Token.T_NOT)) { tokenizer.getThis(Token.T_NULL); TableWorks tw = new TableWorks(session, t); tw.setColNullability(column, false); } else if (token.equals(Token.T_NULL)) { TableWorks tw = new TableWorks(session, t); tw.setColNullability(column, true); } else if (token.equals(Token.T_DEFAULT)) { //alter table alter column set default TableWorks tw = new TableWorks(session, t); int type = column.getType(); int length = column.getSize(); int scale = column.getScale(); Expression expr = processCreateDefaultExpression(type, length, scale); tw.setColDefaultExpression(columnIndex, expr); } else { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } return; } case Token.RESTART : { tokenizer.getThis(Token.T_WITH); long identityStart = tokenizer.getBigint(); int id = t.getIdentityColumn(); if (id == -1) { throw Trace.error(Trace.OPERATION_NOT_SUPPORTED); } t.identitySequence.reset(identityStart); return; } default : { tokenizer.back(); processAlterColumnType(t, column); } } } private void processAlterColumnType(Table table, Column oldCol) throws HsqlException { Column newCol = processCreateColumn(oldCol.columnName); TableWorks tw = new TableWorks(session, table); tw.reTypeColumn(oldCol, newCol); } /** * Responsible for handling tail of ALTER COLUMN ... RENAME ... * @param t table * @param column column * @throws HsqlException */ private void processAlterColumnRename(Table t, Column column) throws HsqlException { String newName = tokenizer.getSimpleName(); boolean isquoted = tokenizer.wasQuotedIdentifier(); if (t.findColumn(newName) > -1) { throw Trace.error(Trace.COLUMN_ALREADY_EXISTS, newName); } t.database.schemaManager.checkColumnIsInView(t, column.columnName.name); session.commit(); session.setScripting(true); t.renameColumn(column, newName, isquoted); } /** * Handles ALTER INDEX. * * @throws HsqlException */ private void processAlterIndex() throws HsqlException { // only the one supported operation, so far processAlterIndexRename(); } private void processAlterSchema() throws HsqlException { // only the one supported operation, so far processAlterSchemaRename(); } /** * Responsible for handling parse and execute of SQL DROP DDL * * @throws HsqlException */ private void processDrop() throws HsqlException { String token; boolean isview; session.checkReadWrite(); session.checkAdmin(); session.setScripting(true); token = tokenizer.getSimpleToken(); isview = false; switch (Token.get(token)) { case Token.INDEX : { processDropIndex(); break; } case Token.SCHEMA : { processDropSchema(); break; } case Token.SEQUENCE : { processDropSequence(); break; } case Token.TRIGGER : { processDropTrigger(); break; } case Token.USER : { processDropUser(); break; } case Token.ROLE : { database.getGranteeManager().dropRole( tokenizer.getSimpleName()); break; } case Token.VIEW : { isview = true; } //fall thru case Token.TABLE : { processDropTable(isview); break; } default : { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } } } /** * Responsible for handling the execution of GRANT and REVOKE SQL * statements. * * @param grant true if grant, false if revoke * @throws HsqlException */ private void processGrantOrRevoke(boolean grant) throws HsqlException { int right; Object accessKey; String token; session.checkAdmin(); session.checkDDLWrite(); session.setScripting(true); right = 0; token = tokenizer.getSimpleToken(); tokenizer.back(); if (!GranteeManager.validRightString(token)) { processRoleGrantOrRevoke(grant); return; } do { token = tokenizer.getSimpleToken(); right |= GranteeManager.getCheckRight(token); } while (tokenizer.isGetThis(Token.T_COMMA)); tokenizer.getThis(Token.T_ON); accessKey = null; if (tokenizer.isGetThis(Token.T_CLASS)) { accessKey = tokenizer.getSimpleName(); if (!tokenizer.wasQuotedIdentifier()) { throw Trace.error(Trace.QUOTED_IDENTIFIER_REQUIRED); } } else { token = tokenizer.getName(); String schema = session.getSchemaName(tokenizer.getLongNameFirst()); Table t = database.schemaManager.getTable(session, token, schema); accessKey = t.getName(); session.setScripting(true); } tokenizer.getThis(grant ? Token.T_TO : Token.T_FROM); token = getUserIdentifier(); GranteeManager gm = database.getGranteeManager(); if (grant) { gm.grant(token, accessKey, right); } else { gm.revoke(token, accessKey, right); } } /** * Responsible for handling CONNECT * * @throws HsqlException */ private void processConnect() throws HsqlException { String userName; String password; User user; tokenizer.getThis(Token.T_USER); userName = getUserIdentifier(); if (tokenizer.isGetThis(Token.T_PASSWORD)) { // legacy log statement or connect statement issued by user password = getPassword(); user = database.getUserManager().getUser(userName, password); session.commit(); session.setUser(user); database.logger.logConnectUser(session); } else if (session.isProcessingLog) { // processing log statement // do not change the user, as isSys() must remain true when processing log session.commit(); } else { // force throw if not log statement tokenizer.getThis(Token.T_PASSWORD); } } /** * Responsible for handling the execution of SET SQL statements * * @throws HsqlException */ private void processSet() throws HsqlException { String token; session.setScripting(true); token = tokenizer.getSimpleToken(); switch (Token.get(token)) { case Token.PROPERTY : { HsqlDatabaseProperties p; session.checkAdmin(); token = tokenizer.getSimpleName(); if (!tokenizer.wasQuotedIdentifier()) { throw Trace.error(Trace.QUOTED_IDENTIFIER_REQUIRED); } p = database.getProperties(); boolean isboolean = p.isBoolean(token); boolean isintegral = p.isIntegral(token); boolean isstring = p.isString(token); Trace.check(isboolean || isintegral || isstring, Trace.ACCESS_IS_DENIED, token); int type = isboolean ? Types.BOOLEAN : isintegral ? Types.INTEGER : Types.VARCHAR; Object value = tokenizer.getInType(type); if (HsqlDatabaseProperties.hsqldb_cache_file_scale.equals( token)) { if (database.logger.hasCache() || ((Integer) value).intValue() != 8) { Trace.throwerror(Trace.ACCESS_IS_DENIED, token); } } p.setDatabaseProperty(token, value.toString().toLowerCase()); p.setDatabaseVariables(); break; } case Token.SCHEMA : { session.setScripting(false); session.setSchema(tokenizer.getSimpleName()); break; } case Token.PASSWORD : { session.checkDDLWrite(); session.getUser().setPassword(getPassword()); break; } case Token.READONLY : { session.commit(); session.setReadOnly(processTrueOrFalse()); break; } case Token.LOGSIZE : { session.checkAdmin(); session.checkDDLWrite(); int i = tokenizer.getInt(); database.logger.setLogSize(i); break; } case Token.SCRIPTFORMAT : { session.checkAdmin(); session.checkDDLWrite(); session.setScripting(false); token = tokenizer.getSimpleToken(); int i = ArrayUtil.find(ScriptWriterBase.LIST_SCRIPT_FORMATS, token); if (i == 0 || i == 1 || i == 3) { database.logger.setScriptType(i); } else { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } break; } case Token.IGNORECASE : { session.checkAdmin(); session.checkDDLWrite(); database.setIgnoreCase(processTrueOrFalse()); break; } case Token.MAXROWS : { session.setScripting(false); int i = tokenizer.getInt(); session.setSQLMaxRows(i); break; } case Token.AUTOCOMMIT : { session.setAutoCommit(processTrueOrFalse()); break; } case Token.TABLE : { session.checkAdmin(); session.checkDDLWrite(); token = tokenizer.getName(); String schema = session.getSchemaNameForWrite( tokenizer.getLongNameFirst()); Table t = database.schemaManager.getTable(session, token, schema); token = tokenizer.getSimpleToken(); session.setScripting(true); switch (Token.get(token)) { default : { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } case Token.SOURCE : { session.checkAdmin(); // SET TABLE <table> SOURCE HEADER if (tokenizer.isGetThis(Token.T_HEADER)) { token = tokenizer.getString(); if (!tokenizer.wasQuotedIdentifier()) { throw Trace.error(Trace.TEXT_TABLE_SOURCE); } try { t.setHeader(token); } catch (Throwable e) { if (session.isProcessingLog() || session.isProcessingScript()) { HsqlException warning = Trace.error(Trace.GENERAL_IO_ERROR, e.getMessage()); session.addWarning(warning); // add an entry to applog too } else { if (e instanceof HsqlException) { throw (HsqlException) e; } else { throw Trace.error( Trace.GENERAL_IO_ERROR, e.getMessage()); } } } break; } // SET TABLE <table> SOURCE ON if (tokenizer.isGetThis(Token.T_ON)) { t.connect(session); database.setMetaDirty(false); break; } // SET TABLE <table> SOURCE OFF if (tokenizer.isGetThis(Token.T_OFF)) { t.disconnect(session); database.setMetaDirty(false); break; } // SET TABLE <table> SOURCE token = tokenizer.getString(); if (!tokenizer.wasQuotedIdentifier()) { throw Trace.error(Trace.TEXT_TABLE_SOURCE); } boolean isDesc = false; isDesc = tokenizer.isGetThis(Token.T_DESC); try { t.setDataSource(session, token, isDesc, false); } catch (Throwable e) { if (session.isProcessingLog() || session.isProcessingScript()) { HsqlException warning = Trace.error(Trace.GENERAL_IO_ERROR, e.getMessage()); session.addWarning(warning); // add an entry to applog too } else { if (e instanceof HsqlException) { throw (HsqlException) e; } else { throw Trace.error(Trace.GENERAL_IO_ERROR, e.getMessage()); } } } break; } case Token.READONLY : { session.checkAdmin(); t.setDataReadOnly(processTrueOrFalse()); database.setMetaDirty(false); break; } case Token.INDEX : { session.checkAdmin(); String roots = (String) tokenizer.getInType(Types.VARCHAR); t.setIndexRoots(roots); break; } } break; } case Token.REFERENTIAL_INTEGRITY : { session.checkAdmin(); session.checkDDLWrite(); session.setScripting(false); database.setReferentialIntegrity(processTrueOrFalse()); break; } case Token.CHECKPOINT : { session.checkAdmin(); session.checkDDLWrite(); tokenizer.getThis(Token.T_DEFRAG); int size = tokenizer.getInt(); database.getProperties().setProperty( HsqlDatabaseProperties.hsqldb_defrag_limit, size); break; } case Token.WRITE_DELAY : { session.checkAdmin(); session.checkDDLWrite(); int delay = 0; tokenizer.getString(); Object value = tokenizer.getAsValue(); if (tokenizer.getType() == Types.INTEGER) { delay = ((Integer) value).intValue(); } else if (Boolean.TRUE.equals(value)) { delay = database.getProperties().getDefaultWriteDelay(); } else if (Boolean.FALSE.equals(value)) { delay = 0; } else { throw Trace.error(Trace.UNEXPECTED_TOKEN); } if (!tokenizer.isGetThis("MILLIS")) { delay *= 1000; } database.logger.setWriteDelay(delay); break; } case Token.FILES : { session.checkAdmin(); session.checkDDLWrite(); tokenizer.getThis(Token.T_INCREMENT); tokenizer.getThis(Token.T_BACKUP); Boolean b = (Boolean) tokenizer.getInType(Types.BOOLEAN); session.checkAdmin(); session.checkDDLWrite(); session.setScripting(false); database.logger.setIncrementalBackup(b.booleanValue()); break; } case Token.DATABASE : { session.checkAdmin(); session.checkDDLWrite(); tokenizer.getThis(Token.T_COLLATION); String cname = tokenizer.getSimpleName(); if (!tokenizer.wasQuotedIdentifier()) { throw Trace.error(Trace.INVALID_IDENTIFIER); } database.collation.setCollation(cname); break; } default : { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } } } /** * 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" */ private boolean processTrueOrFalse() throws HsqlException { String sToken = tokenizer.getSimpleToken(); if (sToken.equals(Token.T_TRUE)) { return true; } else if (sToken.equals(Token.T_FALSE)) { return false; } else { throw Trace.error(Trace.UNEXPECTED_TOKEN, sToken); } } /** * Responsible for handling the execution of COMMIT [WORK] * * @throws HsqlException */ private void processCommit() throws HsqlException { tokenizer.isGetThis(Token.T_WORK); session.commit(); } /** * Responsible for handling the execution of ROLLBACK SQL statements. * * @throws HsqlException */ private void processRollback() throws HsqlException { String token; boolean toSavepoint; token = tokenizer.getSimpleToken(); toSavepoint = false; if (token.equals(Token.T_WORK)) { // do nothing } else if (token.equals(Token.T_TO)) { tokenizer.getThis(Token.T_SAVEPOINT); token = tokenizer.getSimpleName(); toSavepoint = true; } else { tokenizer.back(); } if (toSavepoint) { session.rollbackToSavepoint(token); } else { session.rollback(); } } /** * Responsible for handling the execution of SAVEPOINT SQL statements. * * @throws HsqlException */ private void processSavepoint() throws HsqlException { String token; token = tokenizer.getSimpleName(); session.savepoint(token); } /** * Responsible for handling the execution of SHUTDOWN SQL statements * * @throws HsqlException */ private void processShutdown() throws HsqlException { int closemode; String token; // HUH? We should *NEVER* be able to get here if session is closed if (!session.isClosed()) { session.checkAdmin(); } closemode = Database.CLOSEMODE_NORMAL; token = tokenizer.getSimpleToken(); // fredt - todo - catch misspelt qualifiers here and elsewhere if (token.equals(Token.T_IMMEDIATELY)) { closemode = Database.CLOSEMODE_IMMEDIATELY; } else if (token.equals(Token.T_COMPACT)) { closemode = Database.CLOSEMODE_COMPACT; } else if (token.equals(Token.T_SCRIPT)) { closemode = Database.CLOSEMODE_SCRIPT; } else if (token.equals(Token.T_SEMICOLON)) { // only semicolon is accepted here } else if (token.length() != 0) { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } database.close(closemode); } /** * Responsible for handling CHECKPOINT [DEFRAG]. * * @throws HsqlException */ private void processCheckpoint() throws HsqlException { boolean defrag; String token; session.checkAdmin(); session.checkDDLWrite(); defrag = false; token = tokenizer.getSimpleToken(); if (token.equals(Token.T_DEFRAG)) { defrag = true; } else if (token.equals(Token.T_SEMICOLON)) { // only semicolon is accepted here } else if (token.length() != 0) { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } database.logger.checkpoint(defrag); } // --------------------- new methods / simplifications ------------------------ private HsqlName newIndexHsqlName(String name, boolean isQuoted) throws HsqlException { return HsqlName.isReservedName(name) ? database.nameManager.newAutoName("USER", name) : database.nameManager.newHsqlName(name, isQuoted); } private Table newTable(int type, String name, boolean quoted, HsqlName schema) throws HsqlException { HsqlName tableHsqlName = database.nameManager.newHsqlName(name, quoted); tableHsqlName.schema = schema; switch (type) { case Table.TEMP_TEXT_TABLE : case Table.TEXT_TABLE : { return new TextTable(database, tableHsqlName, type); } default : { return new Table(database, tableHsqlName, type); } } } /** * Checks if the attributes of the Column argument, c, are compatible with * the operation of adding such a Column to the Table argument, t. * * @param t to which to add the Column, c * @param c the Column to add to the Table, t * @throws HsqlException if the operation of adding the Column, c, to * the table t is not valid */ private void checkAddColumn(Table t, Column c) throws HsqlException { boolean canAdd = true; if (t.findColumn(c.columnName.name) != -1) { throw Trace.error(Trace.COLUMN_ALREADY_EXISTS, c.columnName.name); } if (c.isPrimaryKey() && t.hasPrimaryKey()) { canAdd = false; } if (canAdd && !t.isEmpty(session)) { canAdd = c.isNullable() || c.getDefaultExpression() != null; } if (!canAdd) { throw Trace.error(Trace.BAD_ADD_COLUMN_DEFINITION); } } private void checkFKColumnDefaults(Table t, Constraint tc) throws HsqlException { boolean check = tc.core.updateAction == Constraint.SET_DEFAULT; check = check || tc.core.deleteAction == Constraint.SET_DEFAULT; if (check) { int[] localCol = tc.core.mainColArray; for (int j = 0; j < localCol.length; j++) { Column column = t.getColumn(localCol[j]); Expression defExpr = column.getDefaultExpression(); if (defExpr == null) { String columnName = column.columnName.name; throw Trace.error(Trace.NO_DEFAULT_VALUE_FOR_COLUMN, new Object[]{ columnName }); } } } } private void processAlterSequence() throws HsqlException { long start; String name = tokenizer.getName(); String schemaname = tokenizer.getLongNameFirst(); schemaname = session.getSchemaNameForWrite(schemaname); tokenizer.getThis(Token.T_RESTART); tokenizer.getThis(Token.T_WITH); start = tokenizer.getBigint(); NumberSequence seq = database.schemaManager.getSequence(name, schemaname); seq.reset(start); } /** * Handles ALTER INDEX <index-name> RENAME. * * @throws HsqlException */ private void processAlterIndexRename() throws HsqlException { String name = tokenizer.getName(); String schema = session.getSchemaNameForWrite(tokenizer.getLongNameFirst()); tokenizer.getThis(Token.T_RENAME); tokenizer.getThis(Token.T_TO); String newName = tokenizer.getName(); String newSchema = tokenizer.getLongNameFirst(); newSchema = newSchema == null ? schema : session.getSchemaNameForWrite( newSchema); boolean isQuoted = tokenizer.wasQuotedIdentifier(); if (!schema.equals(newSchema)) { throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS); } Table t = database.schemaManager.findUserTableForIndex(session, name, schema); if (t == null) { throw Trace.error(Trace.INDEX_NOT_FOUND, name); } database.schemaManager.checkIndexExists(name, t.getSchemaName(), true); if (HsqlName.isReservedName(name)) { throw Trace.error(Trace.SYSTEM_INDEX, name); } if (HsqlName.isReservedName(newName)) { throw Trace.error(Trace.BAD_INDEX_CONSTRAINT_NAME, newName); } session.setScripting(true); session.commit(); t.getIndex(name).setName(newName, isQuoted); database.schemaManager.renameIndex(name, newName, t.getName()); } /** * Handles ALTER SCHEMA ... RENAME TO . * * @throws HsqlException */ private void processAlterSchemaRename() throws HsqlException { String name = tokenizer.getSimpleName(); tokenizer.getThis(Token.T_RENAME); tokenizer.getThis(Token.T_TO); String newName = tokenizer.getSimpleName(); boolean isQuoted = tokenizer.wasQuotedIdentifier(); database.schemaManager.renameSchema(name, newName, isQuoted); } /** * * @param t table * @throws HsqlException */ private void processAlterTableAddColumn(Table t) throws HsqlException { String token; int colindex = t.getColumnCount(); Column column = processCreateColumn(); checkAddColumn(t, column); if (tokenizer.isGetThis(Token.T_BEFORE)) { token = tokenizer.getSimpleName(); colindex = t.getColumnNr(token); } session.commit(); TableWorks tableWorks = new TableWorks(session, t); tableWorks.addColumn(column, colindex); return; } /** * Responsible for handling tail of ALTER TABLE ... DROP COLUMN ... * * @param t table * @throws HsqlException */ private void processAlterTableDropColumn(Table t) throws HsqlException { String token; int colindex; token = tokenizer.getName(); colindex = t.getColumnNr(token); session.commit(); TableWorks tableWorks = new TableWorks(session, t); tableWorks.dropColumn(colindex); } /** * Responsible for handling tail of ALTER TABLE ... DROP CONSTRAINT ... * * @param t table * @throws HsqlException */ private void processAlterTableDropConstraint(Table t) throws HsqlException { processAlterTableDropConstraint(t, tokenizer.getName()); } /** * Responsible for handling tail of ALTER TABLE ... DROP CONSTRAINT ... * * @param t table * @param name * @throws HsqlException */ private void processAlterTableDropConstraint(Table t, String cname) throws HsqlException { session.commit(); TableWorks tableWorks = new TableWorks(session, t); tableWorks.dropConstraint(cname); return; } /** * If an invalid alias is encountered while processing an old script, * simply discard it. */ private void processCreateAlias() throws HsqlException { String alias; String methodFQN; try { alias = tokenizer.getSimpleName(); } catch (HsqlException e) { if (session.isProcessingScript()) { alias = null; } else { throw e; } } tokenizer.getThis(Token.T_FOR); methodFQN = upgradeMethodFQN(tokenizer.getSimpleName()); if (alias != null) { database.getAliasMap().put(alias, methodFQN); } } private void processCreateIndex(boolean unique) throws HsqlException { Table t; String indexName = tokenizer.getName(); String schema = tokenizer.getLongNameFirst(); boolean indexNameQuoted = tokenizer.wasQuotedIdentifier(); tokenizer.getThis(Token.T_ON); String tablename = tokenizer.getName(); String tableschema = session.getSchemaNameForWrite(tokenizer.getLongNameFirst()); if (schema != null && !schema.equals(tableschema)) { throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS); } t = database.schemaManager.getTable(session, tablename, tableschema); database.schemaManager.checkIndexExists(indexName, t.getSchemaName(), false); HsqlName indexHsqlName = newIndexHsqlName(indexName, indexNameQuoted); int[] indexColumns = processColumnList(t, true); String extra = tokenizer.getSimpleToken(); if (!Token.T_DESC.equals(extra) && !Token.T_ASC.equals(extra)) { tokenizer.back(); } session.commit(); session.setScripting(true); TableWorks tableWorks = new TableWorks(session, t); tableWorks.createIndex(indexColumns, indexHsqlName, unique, false, false); } /** * limitations in Tokenizer dictate that initial value or increment must * be positive * @throws HsqlException */ private void processCreateSequence() throws HsqlException { /* CREATE SEQUENCE <name> [AS {INTEGER | BIGINT}] [START WITH <value>] [INCREMENT BY <value>] */ int type = Types.INTEGER; long increment = 1; long start = 0; String name = tokenizer.getName(); boolean isquoted = tokenizer.wasQuotedIdentifier(); HsqlName schemaname = session.getSchemaHsqlNameForWrite(tokenizer.getLongNameFirst()); if (tokenizer.isGetThis(Token.T_AS)) { String typestring = tokenizer.getSimpleToken(); type = Types.getTypeNr(typestring); Trace.check(type == Types.INTEGER || type == Types.BIGINT, Trace.WRONG_DATA_TYPE); } if (tokenizer.isGetThis(Token.T_START)) { tokenizer.getThis(Token.T_WITH); start = tokenizer.getBigint(); } if (tokenizer.isGetThis(Token.T_INCREMENT)) { tokenizer.getThis(Token.T_BY); increment = tokenizer.getBigint(); } HsqlName hsqlname = database.nameManager.newHsqlName(name, isquoted); hsqlname.schema = schemaname; database.schemaManager.createSequence(hsqlname, start, increment, type); } /** * CREATE SCHEMA PUBLIC in scripts should pass this, so we do not throw * if this schema is created a second time */ private void processCreateSchema() throws HsqlException { String name = tokenizer.getSimpleName(); boolean isquoted = tokenizer.wasQuotedIdentifier(); if (session.isSchemaDefintion()) { throw Trace.error(Trace.INVALID_IDENTIFIER); } tokenizer.getThis(Token.T_AUTHORIZATION); tokenizer.getThis(GranteeManager.DBA_ADMIN_ROLE_NAME); if (database.schemaManager.schemaExists(name)) { if (!session.isProcessingScript) { throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS); } } else { database.schemaManager.createSchema(name, isquoted); } HsqlName schemaName = database.schemaManager.getSchemaHsqlName(name); database.logger.writeToLog(session, DatabaseScript.getSchemaCreateDDL(database, schemaName)); database.logger.writeToLog(session, "SET SCHEMA " + schemaName.statementName); session.startSchemaDefinition(name); session.loggedSchema = session.currentSchema; } private void processCreateUser() throws HsqlException { String name; String password; boolean admin; name = getUserIdentifier(); tokenizer.getThis(Token.T_PASSWORD); password = getPassword(); admin = tokenizer.isGetThis(Token.T_ADMIN); database.getUserManager().createUser(name, password); if (admin) { database.getGranteeManager().grant( name, GranteeManager.DBA_ADMIN_ROLE_NAME); } } private void processDisconnect() throws HsqlException { session.close(); } private void processDropTable(boolean isView) throws HsqlException { boolean ifexists = false; boolean cascade = false; if (tokenizer.isGetThis(Token.T_IF)) { tokenizer.getThis(Token.T_EXISTS); ifexists = true; } String name = tokenizer.getName(); String schema = tokenizer.getLongNameFirst(); if (tokenizer.isGetThis(Token.T_IF)) { tokenizer.getThis(Token.T_EXISTS); ifexists = true; } cascade = tokenizer.isGetThis(Token.T_CASCADE); if (!cascade) { tokenizer.isGetThis(Token.T_RESTRICT); } if (ifexists && schema != null && !database.schemaManager.schemaExists(schema)) { return; } schema = session.getSchemaNameForWrite(schema); database.schemaManager.dropTable(session, name, schema, ifexists, isView, cascade); } private void processDropUser() throws HsqlException { session.checkAdmin(); session.checkDDLWrite(); String userName = getPassword(); if (database.getSessionManager().isUserActive(userName)) { // todo - new error message "cannot drop a user that is currently connected." // NOI18N throw Trace.error(Trace.ACCESS_IS_DENIED); } database.getUserManager().dropUser(userName); } private void processDropSequence() throws HsqlException { boolean ifexists = false; session.checkAdmin(); session.checkDDLWrite(); String name = tokenizer.getName(); String schemaname = session.getSchemaNameForWrite(tokenizer.getLongNameFirst()); if (tokenizer.isGetThis(Token.T_IF)) { tokenizer.getThis(Token.T_EXISTS); ifexists = true; } boolean cascade = tokenizer.isGetThis(Token.T_CASCADE); if (!cascade) { tokenizer.isGetThis(Token.T_RESTRICT); } NumberSequence sequence = database.schemaManager.findSequence(name, schemaname); if (sequence == null) { if (ifexists) { return; } else { throw Trace.error(Trace.SEQUENCE_NOT_FOUND); } } database.schemaManager.checkCascadeDropViews(sequence, cascade); database.schemaManager.dropSequence(sequence); } private void processDropTrigger() throws HsqlException { session.checkAdmin(); session.checkDDLWrite(); String triggername = tokenizer.getName(); String schemaname = session.getSchemaNameForWrite(tokenizer.getLongNameFirst()); database.schemaManager.dropTrigger(session, triggername, schemaname); } private void processDropIndex() throws HsqlException { String name = tokenizer.getName(); String schema = session.getSchemaNameForWrite(tokenizer.getLongNameFirst()); boolean ifexists = false; // accept a table name - no check performed if it is the right table if (tokenizer.isGetThis(Token.T_ON)) { tokenizer.getName(); } if (tokenizer.isGetThis(Token.T_IF)) { tokenizer.getThis(Token.T_EXISTS); ifexists = true; } session.checkAdmin(); session.checkDDLWrite(); database.schemaManager.dropIndex(session, name, schema, ifexists); } private void processDropSchema() throws HsqlException { String name = tokenizer.getSimpleName(); boolean cascade = tokenizer.isGetThis(Token.T_CASCADE); if (!cascade) { tokenizer.isGetThis(Token.T_RESTRICT); } processDropSchema(name, cascade); } private void processDropSchema(String name, boolean cascade) throws HsqlException { if (!database.schemaManager.schemaExists(name)) { throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS); } database.schemaManager.dropSchema(name, cascade); if (name.equals(session.getSchemaName(null))) { session.setSchema(database.schemaManager.getDefaultSchemaName()); } } private Result processExplainPlan() throws IOException, HsqlException { // PRE: we assume only one DML or DQL has been submitted // and simply ignore anything following the first // sucessfully compliled statement String token; Parser parser; int cmd; CompiledStatement cs; Result result; String line; LineNumberReader lnr; tokenizer.getThis(Token.T_PLAN); tokenizer.getThis(Token.T_FOR); parser = new Parser(session, database, tokenizer); token = tokenizer.getSimpleToken(); cmd = Token.get(token); result = Result.newSingleColumnResult("OPERATION", Types.VARCHAR); int brackets = 0; switch (cmd) { case Token.OPENBRACKET : brackets = parser.parseOpenBracketsSelect() + 1; case Token.SELECT : cs = parser.compileSelectStatement(brackets); break; case Token.INSERT : cs = parser.compileInsertStatement(); break; case Token.UPDATE : cs = parser.compileUpdateStatement(); break; case Token.DELETE : cs = parser.compileDeleteStatement(); break; case Token.CALL : cs = parser.compileCallStatement(); break; default : // - No real need to throw, so why bother? // - Just return result with no rows for now // - Later, maybe there will be plan desciptions // for other operations return result; } lnr = new LineNumberReader(new StringReader(cs.describe(session))); while (null != (line = lnr.readLine())) { result.add(new Object[]{ line }); } return result; } // fredt@users 20010701 - patch 1.6.1 by fredt - open <1.60 db files // convert org.hsql.Library aliases from versions < 1.60 to org.hsqldb // fredt@users 20020221 - patch 513005 by sqlbob@users (RMP) - ABS function static final String oldLib = "org.hsql.Library."; static final int oldLibLen = oldLib.length(); static final String newLib = "org.hsqldb.Library."; private static String upgradeMethodFQN(String fqn) { if (fqn.startsWith(oldLib)) { fqn = newLib + fqn.substring(oldLibLen); } else if (fqn.equals("java.lang.Math.abs")) { fqn = "org.hsqldb.Library.abs"; } return fqn; } /** * Processes a SELECT INTO for a new table. */ Result processSelectInto(Result result, HsqlName intoHsqlName, int intoType) throws HsqlException { // fredt@users 20020215 - patch 497872 by Nitin Chauhan // to require column labels in SELECT INTO TABLE int colCount = result.getColumnCount(); for (int i = 0; i < colCount; i++) { if (result.metaData.colLabels[i].length() == 0) { throw Trace.error(Trace.LABEL_REQUIRED); } } // fredt@users 20020221 - patch 513005 by sqlbob@users (RMP) Table t = (intoType == Table.TEXT_TABLE) ? new TextTable(database, intoHsqlName, intoType) : new Table(database, intoHsqlName, intoType); t.addColumns(result.metaData, result.getColumnCount()); t.createPrimaryKey(); database.schemaManager.linkTable(t); // fredt@users 20020221 - patch 513005 by sqlbob@users (RMP) if (intoType == Table.TEXT_TABLE) { try { // Use default lowercase name "<table>.csv" (with invalid // char's converted to underscores): String txtSrc = StringUtil.toLowerSubset(intoHsqlName.name, '_') + ".csv"; t.setDataSource(session, txtSrc, false, true); logTableDDL(t); t.insertIntoTable(session, result); } catch (HsqlException e) { database.schemaManager.dropTable(session, intoHsqlName.name, null, false, false, false); throw (e); } } else { logTableDDL(t); // SELECT .. INTO can't fail because of constraint violation t.insertIntoTable(session, result); } Result uc = new Result(ResultConstants.UPDATECOUNT); uc.updateCount = result.getSize(); return uc; } /** * Logs the DDL for a table created with INTO. * Uses two dummy arguments for getTableDDL() as the new table has no * FK constraints. * * * @param t table * @throws HsqlException */ private void logTableDDL(Table t) throws HsqlException { StringBuffer tableDDL; String sourceDDL; tableDDL = new StringBuffer(); DatabaseScript.getTableDDL(database, t, 0, null, true, tableDDL); sourceDDL = DatabaseScript.getDataSource(t); database.logger.writeToLog(session, tableDDL.toString()); if (sourceDDL != null) { database.logger.writeToLog(session, sourceDDL); database.logger.synchLog(); } } private void processAlterTableAddUniqueConstraint(Table t, HsqlName n) throws HsqlException { int[] col; col = processColumnList(t, false); if (n == null) { n = database.nameManager.newAutoName("CT"); } session.commit(); TableWorks tableWorks = new TableWorks(session, t); tableWorks.createUniqueConstraint(col, n); } private void processAlterTableAddForeignKeyConstraint(Table t, HsqlName n) throws HsqlException { Constraint tc; if (n == null) { n = database.nameManager.newAutoName("FK"); } tc = processCreateFK(t, n); checkFKColumnDefaults(t, tc); t.checkColumnsMatch(tc.core.mainColArray, tc.core.refTable, tc.core.refColArray); session.commit(); TableWorks tableWorks = new TableWorks(session, t); tableWorks.createForeignKey(tc.core.mainColArray, tc.core.refColArray, tc.constName, tc.core.refTable, tc.core.deleteAction, tc.core.updateAction); } private void processAlterTableAddCheckConstraint(Table table, HsqlName name) throws HsqlException { Constraint check; if (name == null) { name = database.nameManager.newAutoName("CT"); } check = new Constraint(name, null, null, null, Constraint.CHECK, Constraint.NO_ACTION, Constraint.NO_ACTION); processCreateCheckConstraintCondition(check); session.commit(); TableWorks tableWorks = new TableWorks(session, table); tableWorks.createCheckConstraint(check, name); } private void processAlterTableAddPrimaryKey(Table t, HsqlName n) throws HsqlException { int[] col; col = processColumnList(t, false); session.commit(); TableWorks tableWorks = new TableWorks(session, t); tableWorks.addPrimaryKey(col, n); } private void processReleaseSavepoint() throws HsqlException { String token; tokenizer.getThis(Token.T_SAVEPOINT); token = tokenizer.getSimpleName(); session.releaseSavepoint(token); } private void processAlterUser() throws HsqlException { String userName; String password; User userObject; userName = getUserIdentifier(); userObject = (User) database.getUserManager().getUsers().get(userName); Trace.check(userObject != null, Trace.USER_NOT_FOUND, userName); tokenizer.getThis(Token.T_SET); tokenizer.getThis(Token.T_PASSWORD); password = getPassword(); userObject.setPassword(password); database.logger.writeToLog(session, userObject.getAlterUserDDL()); database.logger.synchLog(); session.setScripting(false); } private String getUserIdentifier() throws HsqlException { String token = tokenizer.getString(); Tokenizer t = new Tokenizer(token); return t.getSimpleName(); } private String getPassword() throws HsqlException { String token = tokenizer.getString(); return token.toUpperCase(Locale.ENGLISH); } /** * Responsible for handling the execution of GRANT/REVOKE role... * statements. * * @throws HsqlException */ private void processRoleGrantOrRevoke(boolean grant) throws HsqlException { String token; HsqlArrayList list = new HsqlArrayList(); String role; GranteeManager granteeManager = database.getGranteeManager(); do { role = tokenizer.getSimpleToken(); Trace.check(granteeManager.isRole(role), (grant ? Trace.NO_SUCH_ROLE_GRANT : Trace.NO_SUCH_ROLE_REVOKE)); list.add(role); } while (tokenizer.isGetThis(Token.T_COMMA)); tokenizer.getThis(grant ? Token.T_TO : Token.T_FROM); token = getUserIdentifier(); GranteeManager gm = database.getGranteeManager(); for (int i = 0; i < list.size(); i++) { if (grant) { gm.grant(token, (String) list.get(i)); } else { gm.revoke(token, (String) list.get(i)); } } } }

Other HSQLDB examples (source code examples)

Here is a short list of links related to this HSQLDB DatabaseCommandInterpreter.java source code file:

HSQLDB example source code file (DatabaseCommandInterpreter.java)

This example HSQLDB source code file (DatabaseCommandInterpreter.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - HSQLDB tags/keywords

column, constraint, hsqlexception, hsqlexception, hsqlname, hsqlname, io, object, parser, result, string, string, table, tableworks, tableworks, util

The HSQLDB DatabaseCommandInterpreter.java source code

/*
 * For work developed by the HSQL Development Group:
 *
 * Copyright (c) 2001-2010, 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.
 *
 *
 *
 * For work originally developed by the Hypersonic SQL Group:
 *
 * Copyright (c) 1995-2000, The Hypersonic SQL 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 Hypersonic SQL 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 THE HYPERSONIC SQL GROUP,
 * 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.
 *
 * This software consists of voluntary contributions made by many individuals
 * on behalf of the Hypersonic SQL Group.
 */


package org.hsqldb;

import java.io.IOException;
import java.io.LineNumberReader;
import java.io.StringReader;
import java.util.Locale;

import org.hsqldb.HsqlNameManager.HsqlName;
import org.hsqldb.lib.ArrayUtil;
import org.hsqldb.lib.HashMappedList;
import org.hsqldb.lib.HsqlArrayList;
import org.hsqldb.lib.StringUtil;
import org.hsqldb.lib.java.JavaSystem;
import org.hsqldb.persist.HsqlDatabaseProperties;
import org.hsqldb.scriptio.ScriptWriterBase;
import org.hsqldb.scriptio.ScriptWriterText;

/**
 * Provides SQL Interpreter services relative to a Session and
 * its Database.
 *
 * The core functionality of this class was inherited from Hypersonic and
 * extensively rewritten and extended in successive versions of HSQLDB.
 *
 * @author Thomas Mueller (Hypersonic SQL Group)
 * @version 1.8.0
 * @since 1.7.2
 */

// fredt@users 20020221 - patch 513005 by sqlbob@users (RMP) - various corrections
// fredt@users 20020430 - patch 549741 by velichko - ALTER TABLE RENAME
// fredt@users 20020405 - patch 1.7.0 - other ALTER TABLE statements
// tony_lai@users 20020820 - patch 595099 - use user-defined PK name
// tony_lai@users 20020820 - patch 595156 - violation of constraint name
// fredt@users 20020912 - patch 1.7.1 by fredt - log alter statements
// kloska@users 20021030 - patch 1.7.2 - ON UPDATE CASCADE | SET NULL | SET DEFAULT
// kloska@users 20021112 - patch 1.7.2 - ON DELETE SET NULL | SET DEFAULT
// boucherb@users 20020310 - disable ALTER TABLE DDL on VIEWs (avoid NPE)
// fredt@users 20030314 - patch 1.7.2 by gilead@users - drop table if exists syntax
// boucherb@users 20030425 - DDL methods are moved to DatabaseCommandInterpreter.java
// boucherb@users 20030425 - refactoring DDL methods into smaller units
// fredt@users 20030609 - support for ALTER COLUMN SET/DROP DEFAULT / RENAME TO
// wondersonic@users 20031205 - IF EXISTS support for DROP INDEX
// fredt@users 20031224 - support for CREATE SEQUENCE ...
// fredt@users 20041209 - patch by tytar@users to set default table type
class DatabaseCommandInterpreter {

    private Tokenizer tokenizer = new Tokenizer();
    private Database  database;
    private Session   session;

    /**
     * Constructs a new DatabaseCommandInterpreter for the given Session
     *
     * @param s session
     */
    DatabaseCommandInterpreter(Session s) {
        session  = s;
        database = s.getDatabase();
    }

    /**
     * Executes the SQL String. This method is always called from a block
     * synchronized on the database object.
     *
     * @param sql query
     * @return the result of executing the given SQL String
     */
    Result execute(String sql) {

        Result result;
        String token;
        int    cmd;

        JavaSystem.gc();

        result = null;
        cmd    = Token.UNKNOWNTOKEN;

        try {
            tokenizer.reset(sql);

            while (true) {
                tokenizer.setPartMarker();
                session.setScripting(false);

                token = tokenizer.getSimpleToken();

                if (token.length() == 0) {
                    session.endSchemaDefinition();

                    break;
                }

                cmd = Token.get(token);

                if (cmd == Token.SEMICOLON) {
                    session.endSchemaDefinition();

                    continue;
                }

                result = executePart(cmd, token);

                if (result.isError()) {
                    session.endSchemaDefinition();

                    break;
                }

                if (session.getScripting()) {
                    database.logger.writeToLog(session,
                                               tokenizer.getLastPart());
                }
            }
        } catch (Throwable t) {
            try {
                if (session.isSchemaDefintion()) {
                    HsqlName schemaName = session.getSchemaHsqlName(null);

                    database.schemaManager.dropSchema(schemaName.name, true);
                    database.logger.writeToLog(session,
                                               Token.T_DROP + ' '
                                               + Token.T_SCHEMA + ' '
                                               + schemaName.statementName
                                               + ' ' + Token.T_CASCADE);
                    database.logger.synchLog();
                    session.endSchemaDefinition();
                }
            } catch (HsqlException e) {}

            result = new Result(t, tokenizer.getLastPart());
        }

        return result == null ? Session.emptyUpdateCount
                              : result;
    }

    private Result executePart(int cmd, String token) throws Throwable {

        Result result   = Session.emptyUpdateCount;
        int    brackets = 0;

        if (session.isSchemaDefintion()) {
            switch (cmd) {

                case Token.CREATE :
                case Token.GRANT :
                    break;

                default :
                    throw Trace.error(Trace.INVALID_IDENTIFIER,
                                      Trace.IN_SCHEMA_DEFINITION,
                                      new Object[]{ token });
            }
        }

        switch (cmd) {

            case Token.OPENBRACKET : {
                Parser parser = new Parser(session, database, tokenizer);

                brackets = parser.parseOpenBracketsSelect() + 1;
            }
            case Token.SELECT : {
                Parser parser = new Parser(session, database, tokenizer);
                CompiledStatement cStatement =
                    parser.compileSelectStatement(brackets);

                if (cStatement.parameters.length != 0) {
                    Trace.doAssert(
                        false,
                        Trace.getMessage(Trace.ASSERT_DIRECT_EXEC_WITH_PARAM));
                }

                result = session.sqlExecuteCompiledNoPreChecks(cStatement,
                        null);

                break;
            }
            case Token.INSERT : {
                Parser parser = new Parser(session, database, tokenizer);
                CompiledStatement cStatement = parser.compileInsertStatement();

                if (cStatement.parameters.length != 0) {
                    Trace.doAssert(
                        false,
                        Trace.getMessage(Trace.ASSERT_DIRECT_EXEC_WITH_PARAM));
                }

                result = session.sqlExecuteCompiledNoPreChecks(cStatement,
                        null);

                break;
            }
            case Token.UPDATE : {
                Parser parser = new Parser(session, database, tokenizer);
                CompiledStatement cStatement = parser.compileUpdateStatement();

                if (cStatement.parameters.length != 0) {
                    Trace.doAssert(
                        false,
                        Trace.getMessage(Trace.ASSERT_DIRECT_EXEC_WITH_PARAM));
                }

                result = session.sqlExecuteCompiledNoPreChecks(cStatement,
                        null);

                break;
            }
            case Token.DELETE : {
                Parser parser = new Parser(session, database, tokenizer);
                CompiledStatement cStatement = parser.compileDeleteStatement();

                if (cStatement.parameters.length != 0) {
                    Trace.doAssert(
                        false,
                        Trace.getMessage(Trace.ASSERT_DIRECT_EXEC_WITH_PARAM));
                }

                result = session.sqlExecuteCompiledNoPreChecks(cStatement,
                        null);

                break;
            }
            case Token.CALL : {
                Parser parser = new Parser(session, database, tokenizer);
                CompiledStatement cStatement = parser.compileCallStatement();

                if (cStatement.parameters.length != 0) {
                    Trace.doAssert(
                        false,
                        Trace.getMessage(Trace.ASSERT_DIRECT_EXEC_WITH_PARAM));
                }

                result = session.sqlExecuteCompiledNoPreChecks(cStatement,
                        null);

                break;
            }
            case Token.SET :
                processSet();
                break;

            case Token.COMMIT :
                processCommit();
                break;

            case Token.ROLLBACK :
                processRollback();
                break;

            case Token.SAVEPOINT :
                processSavepoint();
                break;

            case Token.RELEASE :
                processReleaseSavepoint();
                break;

            case Token.CREATE :
                processCreate();
                database.setMetaDirty(false);
                break;

            case Token.ALTER :
                processAlter();
                database.setMetaDirty(true);
                break;

            case Token.DROP :
                processDrop();
                database.setMetaDirty(true);
                break;

            case Token.GRANT :
                processGrantOrRevoke(true);
                database.setMetaDirty(false);
                break;

            case Token.REVOKE :
                processGrantOrRevoke(false);
                database.setMetaDirty(true);
                break;

            case Token.CONNECT :
                processConnect();
                database.setMetaDirty(false);
                session.setScripting(false);
                break;

            case Token.DISCONNECT :
                processDisconnect();
                session.setScripting(true);
                break;

            case Token.SCRIPT :
                result = processScript();
                break;

            case Token.SHUTDOWN :
                processShutdown();
                break;

            case Token.CHECKPOINT :
                processCheckpoint();
                break;

            case Token.EXPLAIN :
                result = processExplainPlan();
                break;

            default :
                throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
        }

        return result;
    }

    /**
     * Responsible for parsing and executing the SCRIPT SQL statement
     *
     * @return either an empty result or one in which each row is a DDL or DML
     * @throws IOException
     * @throws HsqlException
     */
    private Result processScript() throws IOException, HsqlException {

        String           token = tokenizer.getString();
        ScriptWriterText dsw   = null;

        session.checkAdmin();

        try {
            if (tokenizer.wasValue()) {
                if (tokenizer.getType() != Types.VARCHAR) {
                    throw Trace.error(Trace.INVALID_IDENTIFIER);
                }

                dsw = new ScriptWriterText(database, token, true, true, true);

                dsw.writeAll();

                return new Result(ResultConstants.UPDATECOUNT);
            } else {
                tokenizer.back();

                return DatabaseScript.getScript(database, false);
            }
        } finally {
            if (dsw != null) {
                dsw.close();
            }
        }
    }

    /**
     *  Responsible for handling CREATE ...
     *
     *  All CREATE command require an ADMIN user except: <p>
     *
     * <pre>
     * CREATE TEMP [MEMORY] TABLE
     * </pre>
     *
     * @throws  HsqlException
     */
    private void processCreate() throws HsqlException {

        boolean unique = false;
        int     tableType;
        boolean isTempTable = false;
        String  token;

        session.checkAdmin();
        session.checkDDLWrite();
        session.setScripting(true);

        if (tokenizer.isGetThis(Token.T_GLOBAL)) {
            tokenizer.getThis(Token.T_TEMPORARY);

            isTempTable = true;
        } else if (tokenizer.isGetThis(Token.T_TEMP)) {
            isTempTable = true;
        } else if (tokenizer.isGetThis(Token.T_TEMPORARY)) {
            isTempTable = true;
        }

        token = tokenizer.getSimpleToken();

        switch (Token.get(token)) {

            // table
            case Token.MEMORY :
                tokenizer.getThis(Token.T_TABLE);
            case Token.TABLE :
                tableType = isTempTable ? Table.TEMP_TABLE
                                        : database.getDefaultTableType();

                processCreateTable(tableType);

                return;

            case Token.CACHED :
                if (isTempTable) {
                    throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
                }

                tokenizer.getThis(Token.T_TABLE);
                processCreateTable(Table.CACHED_TABLE);

                return;

            case Token.TEXT :
                if (isTempTable) {
                    throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
                }

                tokenizer.getThis(Token.T_TABLE);
                processCreateTable(Table.TEXT_TABLE);

                return;

            default :
                if (isTempTable) {
                    throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
                }
        }

        switch (Token.get(token)) {

            // other objects
            case Token.ALIAS :
                processCreateAlias();
                break;

            case Token.SEQUENCE :
                processCreateSequence();
                break;

            case Token.SCHEMA :
                session.setScripting(false);
                processCreateSchema();
                break;

            case Token.TRIGGER :
                processCreateTrigger();
                break;

            case Token.USER :
                processCreateUser();
                break;

            case Token.ROLE :
                database.getGranteeManager().addRole(getUserIdentifier());
                break;

            case Token.VIEW :
                processCreateView();
                break;

            // index
            case Token.UNIQUE :
                unique = true;

                tokenizer.getThis(Token.T_INDEX);

            //fall thru
            case Token.INDEX :
                processCreateIndex(unique);
                break;

            default : {
                throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
            }
        }
    }

    /**
     *  Process a bracketed column list as used in the declaration of SQL
     *  CONSTRAINTS and return an array containing the indexes of the columns
     *  within the table.
     *
     * @param  t table that contains the columns
     * @return  column index map
     * @throws  HsqlException if a column is not found or is duplicate
     */
    private int[] processColumnList(Table t,
                                    boolean acceptAscDesc)
                                    throws HsqlException {

        HashMappedList list = Parser.processColumnList(tokenizer,
            acceptAscDesc);
        int   size = list.size();
        int[] col  = new int[size];

        for (int i = 0; i < size; i++) {
            col[i] = t.getColumnNr((String) list.getKey(i));
        }

        return col;
    }

    /**
     *  Responsible for handling the execution of CREATE TRIGGER SQL
     *  statements. <p>
     *
     *  typical sql is: CREATE TRIGGER tr1 AFTER INSERT ON tab1 CALL "pkg.cls"
     *
     * @throws HsqlException
     */
    private void processCreateTrigger() throws HsqlException {

        Table      t;
        boolean    isForEach;
        boolean    isNowait;
        int        queueSize;
        String     triggerName;
        boolean    isQuoted;
        String     sWhen;
        String     sOper;
        String     tableName;
        String     token;
        String     className;
        TriggerDef td;
        Trigger    o;

        triggerName = tokenizer.getName();

        String schemaname = tokenizer.getLongNameFirst();

        database.schemaManager.checkTriggerExists(triggerName,
                session.getSchemaNameForWrite(schemaname), false);

        isQuoted  = tokenizer.wasQuotedIdentifier();
        isForEach = false;
        isNowait  = false;
        queueSize = TriggerDef.getDefaultQueueSize();
        sWhen     = tokenizer.getSimpleToken();
        sOper     = tokenizer.getSimpleToken();

        tokenizer.getThis(Token.T_ON);

        tableName = tokenizer.getName();

        if (schemaname == null) {
            schemaname =
                session.getSchemaNameForWrite(tokenizer.getLongNameFirst());
        } else if (!schemaname.equals(
                session.getSchemaNameForWrite(tokenizer.getLongNameFirst()))) {
            throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS);
        }

        t = database.schemaManager.getUserTable(session, tableName,
                schemaname);

        if (t.isView()) {
            throw Trace.error(Trace.NOT_A_TABLE);
        }

        session.setScripting(true);

        // "FOR EACH ROW" or "CALL"
        token = tokenizer.getSimpleToken();

        if (token.equals(Token.T_FOR)) {
            token = tokenizer.getSimpleToken();

            if (token.equals(Token.T_EACH)) {
                token = tokenizer.getSimpleToken();

                if (token.equals(Token.T_ROW)) {
                    isForEach = true;

                    // should be 'NOWAIT' or 'QUEUE' or 'CALL'
                    token = tokenizer.getSimpleToken();
                } else {
                    throw Trace.error(Trace.UNEXPECTED_END_OF_COMMAND, token);
                }
            } else {
                throw Trace.error(Trace.UNEXPECTED_END_OF_COMMAND, token);
            }
        }

        if (token.equals(Token.T_NOWAIT)) {
            isNowait = true;

            // should be 'CALL' or 'QUEUE'
            token = tokenizer.getSimpleToken();
        }

        if (token.equals(Token.T_QUEUE)) {
            queueSize = tokenizer.getInt();

            // should be 'CALL'
            token = tokenizer.getSimpleToken();
        }

        if (!token.equals(Token.T_CALL)) {
            throw Trace.error(Trace.UNEXPECTED_END_OF_COMMAND, token);
        }

        className = tokenizer.getSimpleName();

        if (!tokenizer.wasQuotedIdentifier()) {
            throw Trace.error(Trace.UNEXPECTED_END_OF_COMMAND, className);
        }

        HsqlName name = database.nameManager.newHsqlName(triggerName,
            isQuoted);

        td = new TriggerDef(name, sWhen, sOper, isForEach, t, className,
                            isNowait, queueSize, database.classLoader);

        t.addTrigger(td);

        if (td.isValid()) {
            try {

                // start the trigger thread
                td.start();
            } catch (Exception e) {
                throw Trace.error(Trace.UNKNOWN_FUNCTION, e.toString());
            }
        }

        database.schemaManager.registerTriggerName(triggerName, t.getName());

// --
    }

    private Column processCreateColumn() throws HsqlException {

        String   token    = tokenizer.getSimpleName();
        boolean  isQuoted = tokenizer.wasQuotedIdentifier();
        HsqlName hsqlName = database.nameManager.newHsqlName(token, isQuoted);

        return processCreateColumn(hsqlName);
    }

    /**
     *  Responsible for handling the creation of table columns during the
     *  process of executing CREATE TABLE DDL statements.
     *
     *  @param  hsqlName name of the column
     *  @return a Column object with indicated attributes
     *  @throws  HsqlException
     */
    private Column processCreateColumn(HsqlName hsqlName)
    throws HsqlException {

        boolean    isIdentity        = false;
        long       identityStart     = database.firstIdentity;
        long       identityIncrement = 1;
        boolean    isPrimaryKey      = false;
        String     typeName;
        int        type;
        int        length      = 0;
        int        scale       = 0;
        boolean    hasLength   = false;
        boolean    isNullable  = true;
        Expression defaultExpr = null;
        String     token;

        typeName = tokenizer.getSimpleToken();
        type     = Types.getTypeNr(typeName);

        if (type == Types.CHAR) {
            if (tokenizer.isGetThis(Token.T_VARYING)) {
                type = Types.VARCHAR;
            }
        }

        if (typeName.equals(Token.T_IDENTITY)) {
            isIdentity   = true;
            isPrimaryKey = true;
        }

        // fredt - when SET IGNORECASE is in effect, all new VARCHAR columns are defined as VARCHAR_IGNORECASE
        if (type == Types.DOUBLE) {
            tokenizer.isGetThis(Token.T_PRECISION);
        }

        if (tokenizer.isGetThis(Token.T_OPENBRACKET)) {
            hasLength = true;
            length    = tokenizer.getInt();

            Trace.check(Types.acceptsPrecisionCreateParam(type),
                        Trace.UNEXPECTED_TOKEN);

            if (type != Types.TIMESTAMP && type != Types.TIME && length == 0) {
                throw Trace.error(Trace.INVALID_SIZE_PRECISION);
            }

            if (tokenizer.isGetThis(Token.T_COMMA)) {
                Trace.check(Types.acceptsScaleCreateParam(type),
                            Trace.UNEXPECTED_TOKEN);

                scale = tokenizer.getInt();
            }

            tokenizer.getThis(Token.T_CLOSEBRACKET);
        } else if (type == Types.CHAR && database.sqlEnforceStrictSize) {
            length = 1;
        } else if (type == Types.VARCHAR && database.sqlEnforceStrictSize) {
            throw Trace.error(Trace.COLUMN_SIZE_REQUIRED);
        }

        /**
         * @todo fredt - drop support for SET IGNORECASE and replace the
         * type name with a qualifier specifying the case sensitivity of VARCHAR
         */
        if (type == Types.VARCHAR && database.isIgnoreCase()) {
            type = Types.VARCHAR_IGNORECASE;
        }

        if (type == Types.FLOAT && length > 53) {
            throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
        }

        if (type == Types.TIMESTAMP) {
            if (!hasLength) {
                length = 6;
            } else if (length != 0 && length != 6) {
                throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
            }
        }

        if (type == Types.TIME) {
            if (length != 0) {
                throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
            }
        }

        token = tokenizer.getSimpleToken();

        if (token.equals(Token.T_DEFAULT)) {
            defaultExpr = processCreateDefaultExpression(type, length, scale);
            token       = tokenizer.getSimpleToken();
        } else if (token.equals(Token.T_GENERATED)) {
            tokenizer.getThis(Token.T_BY);
            tokenizer.getThis(Token.T_DEFAULT);
            tokenizer.getThis(Token.T_AS);
            tokenizer.getThis(Token.T_IDENTITY);

            if (tokenizer.isGetThis(Token.T_OPENBRACKET)) {
                tokenizer.getThis(Token.T_START);
                tokenizer.getThis(Token.T_WITH);

                identityStart = tokenizer.getBigint();

                if (tokenizer.isGetThis(Token.T_COMMA)) {
                    tokenizer.getThis(Token.T_INCREMENT);
                    tokenizer.getThis(Token.T_BY);

                    identityIncrement = tokenizer.getBigint();
                }

                tokenizer.getThis(Token.T_CLOSEBRACKET);
            }

            isIdentity   = true;
            isPrimaryKey = true;
            token        = tokenizer.getSimpleToken();
        }

        // fredt@users - accept IDENTITY before or after NOT NULL
        if (token.equals(Token.T_IDENTITY)) {
            isIdentity   = true;
            isPrimaryKey = true;
            token        = tokenizer.getSimpleToken();
        }

        if (token.equals(Token.T_NULL)) {
            token = tokenizer.getSimpleToken();
        } else if (token.equals(Token.T_NOT)) {
            tokenizer.getThis(Token.T_NULL);

            isNullable = false;
            token      = tokenizer.getSimpleToken();
        }

        if (token.equals(Token.T_IDENTITY)) {
            if (isIdentity) {
                throw Trace.error(Trace.SECOND_PRIMARY_KEY, Token.T_IDENTITY);
            }

            isIdentity   = true;
            isPrimaryKey = true;
            token        = tokenizer.getSimpleToken();
        }

        if (token.equals(Token.T_PRIMARY)) {
            tokenizer.getThis(Token.T_KEY);

            isPrimaryKey = true;
        } else {
            tokenizer.back();
        }

        // make sure IDENTITY and DEFAULT are not used together
        if (isIdentity && defaultExpr != null) {
            throw Trace.error(Trace.UNEXPECTED_TOKEN, Token.T_DEFAULT);
        }

        Column column = new Column(hsqlName, isNullable, type, length, scale,
                                   isPrimaryKey, defaultExpr);

        column.setIdentity(isIdentity, identityStart, identityIncrement);

        return column;
    }

    /**
     * @param type data type of column
     * @param length maximum length of column
     * @throws HsqlException
     * @return new Expression
     */
    private Expression processCreateDefaultExpression(int type, int length,
            int scale) throws HsqlException {

        if (type == Types.OTHER) {
            throw Trace.error(Trace.WRONG_DEFAULT_CLAUSE);
        }

        Parser     parser = new Parser(session, database, tokenizer);
        Expression expr   = parser.readDefaultClause(type);

        expr.resolveTypes(session);

        int newType = expr.getType();

        if (newType == Expression.VALUE || newType == Expression.TRUE
                || newType == Expression.FALSE
                || (newType == Expression.FUNCTION
                    && expr.function.isSimple)) {
            Object defValTemp;

            try {
                defValTemp = expr.getValue(session, type);
            } catch (HsqlException e) {
                throw Trace.error(Trace.WRONG_DEFAULT_CLAUSE);
            }

            if (defValTemp != null && database.sqlEnforceStrictSize) {
                try {
                    Column.enforceSize(defValTemp, type, length, scale, true);
                } catch (HsqlException e) {

                    // default value is too long for fixed size column
                    throw Trace.error(Trace.WRONG_DEFAULT_CLAUSE);
                }
            }

            return expr;
        }

        throw Trace.error(Trace.WRONG_DEFAULT_CLAUSE);
    }

    public static void checkBooleanDefault(String s,
                                           int type) throws HsqlException {

        if (type != Types.BOOLEAN || s == null) {
            return;
        }

        s = s.toUpperCase();

        if (s.equals(Token.T_TRUE) || s.equals(Token.T_FALSE)) {
            return;
        }

        if (s.equals("0") || s.equals("1")) {
            return;
        }

        throw Trace.error(Trace.WRONG_DEFAULT_CLAUSE, s);
    }

    /**
     * Responsible for handling constraints section of CREATE TABLE ...
     *
     * @param t table
     * @param constraint CONSTRAINT keyword used
     * @param primarykeycolumn primary columns
     * @throws HsqlException
     * @return list of constraints
     */
    private HsqlArrayList processCreateConstraints(Table t,
            boolean constraint, int[] primarykeycolumn) throws HsqlException {

        String        token;
        HsqlArrayList tcList;
        Constraint    tempConst;
        HsqlName      pkHsqlName;

// fredt@users 20020225 - comment
// HSQLDB relies on primary index to be the first one defined
// and needs original or system added primary key before any
// non-unique index is created
        tcList = new HsqlArrayList();
        tempConst = new Constraint(null, primarykeycolumn, null, null,
                                   Constraint.MAIN, Constraint.NO_ACTION,
                                   Constraint.NO_ACTION);

// tony_lai@users 20020820 - patch 595099
        pkHsqlName = null;

        tcList.add(tempConst);

        if (!constraint) {
            return tcList;
        }

        while (true) {
            HsqlName cname = null;

            if (tokenizer.isGetThis(Token.T_CONSTRAINT)) {
                token = tokenizer.getName();

                String constraintSchema = tokenizer.getLongNameFirst();

                if (constraintSchema != null) {
                    constraintSchema = session.getSchemaNameForWrite(
                        tokenizer.getLongNameFirst());

                    if (!t.getSchemaName().equals(constraintSchema)) {
                        throw Trace.error(
                            Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS,
                            constraintSchema);
                    }
                }

                cname = database.nameManager.newHsqlName(token,
                        tokenizer.wasQuotedIdentifier());
            }

            token = tokenizer.getSimpleToken();

            switch (Token.get(token)) {

                case Token.PRIMARY : {
                    tokenizer.getThis(Token.T_KEY);

                    // tony_lai@users 20020820 - patch 595099
                    pkHsqlName = cname;

                    int[]      cols = processColumnList(t, false);
                    Constraint mainConst;

                    mainConst = (Constraint) tcList.get(0);

                    if (mainConst.core.mainColArray != null) {
                        if (!ArrayUtil.areEqual(mainConst.core.mainColArray,
                                                cols, cols.length, true)) {
                            throw Trace.error(Trace.SECOND_PRIMARY_KEY);
                        }
                    }

                    mainConst.core.mainColArray = cols;
                    mainConst.constName         = pkHsqlName;

                    break;
                }
                case Token.UNIQUE : {
                    int[] col = processColumnList(t, false);

                    if (cname == null) {
                        cname = database.nameManager.newAutoName("CT");
                    }

                    tempConst = new Constraint(cname, col, null, null,
                                               Constraint.UNIQUE,
                                               Constraint.NO_ACTION,
                                               Constraint.NO_ACTION);

                    tcList.add(tempConst);

                    break;
                }
                case Token.FOREIGN : {
                    tokenizer.getThis(Token.T_KEY);

                    tempConst = processCreateFK(t, cname);

                    if (tempConst.core.refColArray == null) {
                        Constraint mainConst = (Constraint) tcList.get(0);

                        tempConst.core.refColArray =
                            mainConst.core.mainColArray;

                        if (tempConst.core.refColArray == null) {
                            throw Trace.error(Trace.CONSTRAINT_NOT_FOUND,
                                              Trace.TABLE_HAS_NO_PRIMARY_KEY);
                        }
                    }

                    checkFKColumnDefaults(t, tempConst);
                    t.checkColumnsMatch(tempConst.core.mainColArray,
                                        tempConst.core.refTable,
                                        tempConst.core.refColArray);
                    tcList.add(tempConst);

                    break;
                }
                case Token.CHECK : {
                    if (cname == null) {
                        cname = database.nameManager.newAutoName("CT");
                    }

                    tempConst = new Constraint(cname, null, null, null,
                                               Constraint.CHECK,
                                               Constraint.NO_ACTION,
                                               Constraint.NO_ACTION);

                    processCreateCheckConstraintCondition(tempConst);
                    tcList.add(tempConst);

                    break;
                }
            }

            token = tokenizer.getSimpleToken();

            if (token.equals(Token.T_COMMA)) {
                continue;
            }

            if (token.equals(Token.T_CLOSEBRACKET)) {
                break;
            }

            throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
        }

        return tcList;
    }

    /**
     * Responsible for handling check constraints section of CREATE TABLE ...
     *
     * @param c check constraint
     * @throws HsqlException
     */
    private void processCreateCheckConstraintCondition(Constraint c)
    throws HsqlException {

        tokenizer.getThis(Token.T_OPENBRACKET);

        Parser     parser    = new Parser(session, database, tokenizer);
        Expression condition = parser.parseExpression();

        tokenizer.getThis(Token.T_CLOSEBRACKET);

        c.core.check = condition;
    }

    /**
     * Responsible for handling the execution CREATE TABLE SQL statements.
     *
     * @param type Description of the Parameter
     * @throws HsqlException
     */
    private void processCreateTable(int type) throws HsqlException {

        String token = tokenizer.getName();
        HsqlName schemaname =
            session.getSchemaHsqlNameForWrite(tokenizer.getLongNameFirst());

        database.schemaManager.checkUserTableNotExists(session, token,
                schemaname.name);

        boolean isnamequoted = tokenizer.wasQuotedIdentifier();
        int[]   pkCols       = null;
        int     colIndex     = 0;
        boolean constraint   = false;
        Table   t            = newTable(type, token, isnamequoted, schemaname);

        tokenizer.getThis(Token.T_OPENBRACKET);

        while (true) {
            token = tokenizer.getString();

            switch (Token.get(token)) {

                case Token.CONSTRAINT :
                case Token.PRIMARY :
                case Token.FOREIGN :
                case Token.UNIQUE :
                case Token.CHECK :

                    // fredt@users : check for quoted reserved words used as column names
                    constraint = !tokenizer.wasQuotedIdentifier()
                                 && !tokenizer.wasLongName();
            }

            tokenizer.back();

            if (constraint) {
                break;
            }

            Column newcolumn = processCreateColumn();

            t.addColumn(newcolumn);

            if (newcolumn.isPrimaryKey()) {
                Trace.check(pkCols == null, Trace.SECOND_PRIMARY_KEY,
                            newcolumn.columnName.name);

                pkCols = new int[]{ colIndex };
            }

            token = tokenizer.getSimpleToken();

            if (token.equals(Token.T_COMMA)) {
                colIndex++;

                continue;
            }

            if (token.equals(Token.T_CLOSEBRACKET)) {
                break;
            }

            throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
        }

        HsqlArrayList tempConstraints = processCreateConstraints(t,
            constraint, pkCols);

        if (tokenizer.isGetThis(Token.T_ON)) {
            if (!t.isTemp) {
                throw Trace.error(Trace.UNEXPECTED_TOKEN, Token.T_ON);
            }

            tokenizer.getThis(Token.T_COMMIT);

            token = tokenizer.getSimpleToken();

            if (token.equals(Token.T_DELETE)) {}
            else if (token.equals(Token.T_PRESERVE)) {
                t.onCommitPreserve = true;
            } else {
                throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
            }

            tokenizer.getThis(Token.T_ROWS);
        }

        try {
            session.commit();

            Constraint primaryConst = (Constraint) tempConstraints.get(0);

            t.createPrimaryKey(null, primaryConst.core.mainColArray, true);

            if (primaryConst.core.mainColArray != null) {
                if (primaryConst.constName == null) {
                    primaryConst.constName = t.makeSysPKName();
                }

                Constraint newconstraint =
                    new Constraint(primaryConst.constName, t,
                                   t.getPrimaryIndex(),
                                   Constraint.PRIMARY_KEY);

                t.addConstraint(newconstraint);
                database.schemaManager.registerConstraintName(
                    primaryConst.constName.name, t.getName());
            }

            for (int i = 1; i < tempConstraints.size(); i++) {
                Constraint tempConst = (Constraint) tempConstraints.get(i);

                if (tempConst.constType == Constraint.UNIQUE) {
                    TableWorks tableWorks = new TableWorks(session, t);

                    tableWorks.createUniqueConstraint(
                        tempConst.core.mainColArray, tempConst.constName);

                    t = tableWorks.getTable();
                }

                if (tempConst.constType == Constraint.FOREIGN_KEY) {
                    TableWorks tableWorks = new TableWorks(session, t);

                    tableWorks.createForeignKey(tempConst.core.mainColArray,
                                                tempConst.core.refColArray,
                                                tempConst.constName,
                                                tempConst.core.refTable,
                                                tempConst.core.deleteAction,
                                                tempConst.core.updateAction);

                    t = tableWorks.getTable();
                }

                if (tempConst.constType == Constraint.CHECK) {
                    TableWorks tableWorks = new TableWorks(session, t);

                    tableWorks.createCheckConstraint(tempConst,
                                                     tempConst.constName);

                    t = tableWorks.getTable();
                }
            }

            database.schemaManager.linkTable(t);
        } catch (HsqlException e) {

// fredt@users 20020225 - comment
// if a HsqlException is thrown while creating table, any foreign key that has
// been created leaves it modification to the expTable in place
// need to undo those modifications. This should not happen in practice.
            database.schemaManager.removeExportedKeys(t);
            database.schemaManager.removeIndexNames(t.tableName);
            database.schemaManager.removeConstraintNames(t.tableName);

            throw e;
        }
    }

// fredt@users 20020221 - patch 520213 by boucherb@users - self reference FK
// allows foreign keys that reference a column in the same table

    /**
     * @param t table
     * @param cname foreign key name
     * @throws HsqlException
     * @return constraint
     */
    private Constraint processCreateFK(Table t,
                                       HsqlName cname) throws HsqlException {

        int[]  localcol;
        int[]  expcol;
        String expTableName;
        Table  expTable;
        String token;

        localcol = processColumnList(t, false);

        tokenizer.getThis(Token.T_REFERENCES);

        expTableName = tokenizer.getName();

        String constraintSchema = tokenizer.getLongNameFirst();

        if (constraintSchema != null) {
            constraintSchema =
                session.getSchemaNameForWrite(tokenizer.getLongNameFirst());

            if (!t.getSchemaName().equals(constraintSchema)) {
                throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS,
                                  constraintSchema);
            }
        }

        if (t.getName().name.equals(expTableName)) {
            expTable = t;
        } else {
            expTable = database.schemaManager.getTable(session, expTableName,
                    t.getSchemaName());
        }

        expcol = null;
        token  = tokenizer.getSimpleToken();

        tokenizer.back();

        if (token.equals(Token.T_OPENBRACKET)) {
            expcol = processColumnList(expTable, false);
        } else {
            if (expTable.getPrimaryKey() == null) {

                // getPrimaryKey() == null is true while creating the table
                // fredt - FK statement is part of CREATE TABLE and is self-referencing
                // reference must be to same table being created
                // it is resolved in the calling method
                Trace.check(t == expTable, Trace.TABLE_HAS_NO_PRIMARY_KEY);
            } else {
                if (expTable.hasPrimaryKey()) {
                    expcol = expTable.getPrimaryKey();
                } else {
                    throw Trace.error(Trace.CONSTRAINT_NOT_FOUND,
                                      Trace.TABLE_HAS_NO_PRIMARY_KEY);
                }
            }
        }

        token = tokenizer.getSimpleToken();

        // -- 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 = Constraint.NO_ACTION;
        int updateAction = Constraint.NO_ACTION;

        while (token.equals(Token.T_ON)) {
            token = tokenizer.getSimpleToken();

            if (deleteAction == Constraint.NO_ACTION
                    && token.equals(Token.T_DELETE)) {
                token = tokenizer.getSimpleToken();

                if (token.equals(Token.T_SET)) {
                    token = tokenizer.getSimpleToken();

                    if (token.equals(Token.T_DEFAULT)) {
                        deleteAction = Constraint.SET_DEFAULT;
                    } else if (token.equals(Token.T_NULL)) {
                        deleteAction = Constraint.SET_NULL;
                    } else {
                        throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
                    }
                } else if (token.equals(Token.T_CASCADE)) {
                    deleteAction = Constraint.CASCADE;
                } else if (token.equals(Token.T_RESTRICT)) {

                    // LEGACY compatibility/usability
                    // - same as NO ACTION or nothing at all
                } else {
                    tokenizer.matchThis(Token.T_NO);
                    tokenizer.getThis(Token.T_ACTION);
                }
            } else if (updateAction == Constraint.NO_ACTION
                       && token.equals(Token.T_UPDATE)) {
                token = tokenizer.getSimpleToken();

                if (token.equals(Token.T_SET)) {
                    token = tokenizer.getSimpleToken();

                    if (token.equals(Token.T_DEFAULT)) {
                        updateAction = Constraint.SET_DEFAULT;
                    } else if (token.equals(Token.T_NULL)) {
                        updateAction = Constraint.SET_NULL;
                    } else {
                        throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
                    }
                } else if (token.equals(Token.T_CASCADE)) {
                    updateAction = Constraint.CASCADE;
                } else if (token.equals(Token.T_RESTRICT)) {

                    // LEGACY compatibility/usability
                    // - same as NO ACTION or nothing at all
                } else {
                    tokenizer.matchThis(Token.T_NO);
                    tokenizer.getThis(Token.T_ACTION);
                }
            } else {
                throw Trace.error(Trace.UNEXPECTED_TOKEN, token);
            }

            token = tokenizer.getSimpleToken();
        }

        tokenizer.back();

        if (cname == null) {
            cname = database.nameManager.newAutoName("FK");
        }

        return new Constraint(cname, localcol, expTable, expcol,
                              Constraint.FOREIGN_KEY, deleteAction,
                              updateAction);
    }

    /**
     * Responsible for handling the execution CREATE VIEW SQL statements.
     *
     * @throws HsqlException
     */
    private void processCreateView() throws HsqlException {

        String name = tokenizer.getName();
        HsqlName schemaname =
            session.getSchemaHsqlNameForWrite(tokenizer.getLongNameFirst());
        int logposition = tokenizer.getPartMarker();

        database.schemaManager.checkUserViewNotExists(session, name,
                schemaname.name);

        HsqlName viewHsqlName = database.nameManager.newHsqlName(name,
            tokenizer.wasQuotedIdentifier());

        viewHsqlName.schema = schemaname;

        HsqlName[] colList = null;

        if (tokenizer.isGetThis(Token.T_OPENBRACKET)) {
            try {
                HsqlArrayList list = Parser.getColumnNames(database, null,
                    tokenizer, true);

                colList = new HsqlName[list.size()];
                colList = (HsqlName[]) list.toArray(colList);
            } catch (HsqlException e) {

                // fredt - a bug in 1.8.0.0 and previous versions causes view
                // definitions to script without double quotes around column names
                // in certain cases; the workaround here discards the column
                // names
                if (database.isStoredFileAccess()
                        && session.isProcessingScript()) {
                    while (true) {
                        String token = tokenizer.getString();

                        if (token.equals(Token.T_CLOSEBRACKET)
                                || token.equals("")) {
                            break;
                        }
                    }
                } else {
                    throw e;
                }
            }
        }

        tokenizer.getThis(Token.T_AS);
        tokenizer.setPartMarker();

        Parser parser   = new Parser(session, database, tokenizer);
        int    brackets = parser.parseOpenBracketsSelect();
        Select select;

        // accept ORDER BY or ORDRY BY with LIMIT - accept unions
        select = parser.parseSelect(brackets, true, false, true, true);

        if (select.sIntoTable != null) {
            throw (Trace.error(Trace.INVALID_IDENTIFIER, Token.INTO));
        }

        select.prepareResult(session);

        View view = new View(session, database, viewHsqlName,
                             tokenizer.getLastPart(), colList);

        session.commit();
        database.schemaManager.linkTable(view);
        tokenizer.setPartMarker(logposition);
    }

    /**
     * Responsible for handling tail of ALTER TABLE ... RENAME ...
     * @param t table
     * @throws HsqlException
     */
    private void processAlterTableRename(Table t) throws HsqlException {

        String  schema = t.getSchemaName();
        String  newName;
        boolean isquoted;

        // ensures that if temp table, it also belongs to this session
/*
        if (!t.equals(session, name)) {
            throw Trace.error(Trace.TABLE_NOT_FOUND);
        }
*/
        tokenizer.getThis(Token.T_TO);

        newName = tokenizer.getName();

        String newSchema = tokenizer.getLongNameFirst();

        isquoted  = tokenizer.wasQuotedIdentifier();
        newSchema = newSchema == null ? schema
                                      : session.getSchemaNameForWrite(
                                          newSchema);

        if (!schema.equals(newSchema)) {
            throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS);
        }

        database.schemaManager.checkUserTableNotExists(session, newName,
                schema);
        session.commit();
        session.setScripting(true);
        database.schemaManager.renameTable(session, t, newName, isquoted);
    }

    /**
     * Handles ALTER TABLE statements. <p>
     *
     * ALTER TABLE <name> RENAME TO 
     * ALTER INDEX <name> RENAME TO 
     *
     * ALTER TABLE <name> ADD CONSTRAINT  FOREIGN KEY (
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.