/* Copyright (c) 2001-2009, The HSQL Development Group * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the HSQL Development Group nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG, * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.hsqldb; import org.hsqldb.HsqlNameManager.HsqlName; import org.hsqldb.lib.ArrayUtil; import org.hsqldb.lib.HsqlArrayList; import org.hsqldb.lib.HsqlList; import org.hsqldb.lib.OrderedHashSet; import org.hsqldb.persist.HsqlDatabaseProperties; import org.hsqldb.scriptio.ScriptWriterBase; import org.hsqldb.store.ValuePool; import org.hsqldb.types.Type; /** * Parser for session and management statements * * @author Fred Toussi (fredt@users dot sourceforge.net) * @version 1.9.0 * @since 1.9.0 */ public class ParserCommand extends ParserDDL { ParserCommand(Session session, Scanner t) { super(session, t); } Statement compileStatement() { Statement cs = compilePart(); if (token.tokenType == Tokens.X_ENDPARSE) { if (cs.getSchemalName() == null) { cs.setSchemaHsqlName(session.getCurrentSchemaHsqlName()); } return cs; } throw unexpectedToken(); } HsqlArrayList compileStatements(String sql, int returnType) { HsqlArrayList list = new HsqlArrayList(); Statement cs = null; reset(sql); while (true) { if (token.tokenType == Tokens.X_ENDPARSE) { break; } compileContext.reset(); cs = compilePart(); if (cs == null) { list.add(cs); } else { list.add(cs); } } if (returnType != StatementTypes.RETURN_ANY) { int group = cs.getGroup(); if (group == StatementTypes.X_SQL_DATA) { if (returnType == StatementTypes.RETURN_COUNT) { throw Error.error(ErrorCode.X_07503); } } else if (returnType == StatementTypes.RETURN_RESULT) { throw Error.error(ErrorCode.X_07504); } } return list; } private Statement compilePart() { Statement cs = null; setParsePosition(getPosition()); if (token.tokenType == Tokens.X_STARTPARSE) { read(); } switch (token.tokenType) { // DQL case Tokens.WITH : case Tokens.OPENBRACKET : case Tokens.VALUES : case Tokens.TABLE : case Tokens.SELECT : { cs = compileCursorSpecification(); break; } // DML case Tokens.INSERT : { cs = compileInsertStatement(RangeVariable.emptyArray); break; } case Tokens.UPDATE : { cs = compileUpdateStatement(RangeVariable.emptyArray); break; } case Tokens.MERGE : { cs = compileMergeStatement(RangeVariable.emptyArray); break; } case Tokens.DELETE : { cs = compileDeleteStatement(RangeVariable.emptyArray); break; } case Tokens.TRUNCATE : { cs = compileDeleteStatement(RangeVariable.emptyArray); break; } // PROCEDURE case Tokens.CALL : { cs = compileCallStatement( session.sessionContext.sessionVariablesRange, false); break; } // SQL SESSION case Tokens.SET : cs = compileSet(); break; case Tokens.START : cs = compileStartTransaction(); break; case Tokens.COMMIT : cs = compileCommit(); break; case Tokens.ROLLBACK : cs = compileRollback(); break; case Tokens.SAVEPOINT : cs = compileSavepoint(); break; case Tokens.RELEASE : cs = compileReleaseSavepoint(); break; // DDL case Tokens.CREATE : cs = compileCreate(); break; case Tokens.ALTER : cs = compileAlter(); break; case Tokens.DROP : cs = compileDrop(); break; case Tokens.GRANT : case Tokens.REVOKE : cs = compileGrantOrRevoke(); break; // HSQL SESSION case Tokens.LOCK : cs = compileLock(); break; case Tokens.CONNECT : cs = compileConnect(); break; case Tokens.DISCONNECT : cs = compileDisconnect(); break; // HSQL COMMAND case Tokens.SCRIPT : cs = compileScript(); break; case Tokens.SHUTDOWN : cs = compileShutdown(); break; case Tokens.BACKUP : cs = compileBackup(); break; case Tokens.CHECKPOINT : cs = compileCheckpoint(); break; case Tokens.EXPLAIN : cs = compileExplainPlan(); break; case Tokens.DECLARE : cs = compileSessionVariableDeclaration(); break; default : throw unexpectedToken(); } if (cs.type != StatementTypes.SET_SESSION_AUTHORIZATION) { cs.setSQL(getLastPart()); } if (token.tokenType == Tokens.SEMICOLON) { read(); } else if (token.tokenType == Tokens.X_ENDPARSE) {} return cs; } private Statement compileSessionVariableDeclaration() { ColumnSchema variable = readLocalVariableDeclarationOrNull(); Object[] args = new Object[]{ variable }; Statement cs = new StatementSession(StatementTypes.DECLARE_VARIABLE, args); return cs; } private Statement compileScript() { String name = null; read(); if (token.tokenType == Tokens.X_VALUE) { if (token.dataType.typeCode != Types.SQL_CHAR) { throw Error.error(ErrorCode.X_42581); } name = token.tokenString; read(); } Object[] args = new Object[]{ name }; Statement cs = new StatementCommand(StatementTypes.DATABASE_SCRIPT, args, database.getCatalogName(), null); return cs; } private Statement compileConnect() { String userName; String password = null; read(); readThis(Tokens.USER); checkIsSimpleName(); userName = token.tokenString; read(); readThis(Tokens.PASSWORD); password = readPassword(); Expression[] args = new Expression[] { new ExpressionValue(userName, Type.SQL_VARCHAR), new ExpressionValue(password, Type.SQL_VARCHAR) }; Statement cs = new StatementSession(StatementTypes.SET_SESSION_AUTHORIZATION, args); return cs; } private Statement compileSetDefault() { read(); switch (token.tokenType) { case Tokens.INITIAL : { read(); readThis(Tokens.SCHEMA); HsqlName schema = database.schemaManager.getSchemaHsqlName( token.tokenString); read(); Object[] args = new Object[]{ schema }; return new StatementCommand( StatementTypes.SET_DATABASE_DEFAULT_INITIAL_SCHEMA, args, null, null); } case Tokens.RESULT : { read(); readThis(Tokens.MEMORY); readThis(Tokens.SIZE); int size = readInteger(); Object[] args = new Object[]{ new Integer(size) }; return new StatementCommand( StatementTypes.SET_DATABASE_RESULT_MEMORY_ROWS, args, null, null); } case Tokens.TABLE : { read(); readThis(Tokens.TYPE); int type = TableBase.MEMORY_TABLE; switch (token.tokenType) { case Tokens.MEMORY : break; case Tokens.CACHED : type = TableBase.CACHED_TABLE; break; default : throw unexpectedToken(); } read(); Object[] args = new Object[]{ Integer.valueOf(type) }; return new StatementCommand( StatementTypes.SET_DATABASE_DEFAULT_TABLE_TYPE, args, null, null); } default : throw unexpectedToken(); } } private Statement compileSetProperty() { read(); String property; Object value; HsqlDatabaseProperties props; checkIsSimpleName(); checkIsDelimitedIdentifier(); property = token.tokenString; props = database.getProperties(); boolean isboolean = props.isBoolean(token.tokenString); boolean isintegral = props.isIntegral(token.tokenString); boolean isstring = props.isString(token.tokenString); if (!(isboolean || isintegral || isstring)) { throw Error.error(ErrorCode.X_42511); } int typeCode = isboolean ? Types.SQL_BOOLEAN : isintegral ? Types.SQL_INTEGER : Types.SQL_CHAR; read(); if (token.tokenType == Tokens.TRUE) { value = Boolean.TRUE; } else if (token.tokenType == Tokens.FALSE) { value = Boolean.FALSE; } else { checkIsValue(); value = token.tokenValue; if (token.dataType.typeCode != typeCode) { throw Error.error(ErrorCode.X_42565, token.tokenString); } } read(); Object[] args = new Object[] { property, value }; return new StatementCommand(StatementTypes.SET_DATABASE_PROPERTY, args, null, null); } private Statement compileSet() { int position = super.getPosition(); session.setScripting(false); read(); switch (token.tokenType) { case Tokens.SCHEMA : { read(); Expression e = XreadValueSpecificationOrNull(); if (e == null) { HsqlName name = readSchemaName(); Object[] args = new Object[]{ name }; return new StatementSession(StatementTypes.SET_SCHEMA, args); } if (!e.getDataType().isCharacterType()) { throw Error.error(ErrorCode.X_0P000); } if (e.getType() != OpTypes.VALUE && (e.getType() != OpTypes.SQL_FUNCTION || !((FunctionSQL) e).isValueFunction())) { throw Error.error(ErrorCode.X_0P000); } Expression[] args = new Expression[]{ e }; return new StatementSession(StatementTypes.SET_SCHEMA, args); } case Tokens.TIME : { read(); return compileSetTimeZone(); } case Tokens.ROLE : { read(); return compileSetRole(); } case Tokens.SESSION : { read(); return compileSessionSettings(); } case Tokens.TRANSACTION : { read(); Object[] args = processTransactionCharacteristics(); if (args[0] == null && args[1] == null) { throw unexpectedToken(); } return new StatementSession(StatementTypes.SET_TRANSACTION, args); } case Tokens.AUTOCOMMIT : { read(); boolean mode = processTrueOrFalse(); Object[] args = new Object[]{ Boolean.valueOf(mode) }; return new StatementSession( StatementTypes.SET_SESSION_AUTOCOMMIT, args); } // deprecated case Tokens.READONLY : { read(); boolean readonly = processTrueOrFalse(); Object[] args = new Object[]{ Boolean.valueOf(readonly) }; return new StatementSession( StatementTypes.SET_SESSION_CHARACTERISTICS, args); } case Tokens.LOGSIZE : { read(); checkDatabaseUpdateAuthorisation(); int size = readInteger(); Object[] args = new Object[]{ new Integer(size) }; return new StatementCommand( StatementTypes.SET_DATABASE_FILES_LOG_SIZE, args, null, null); } case Tokens.SCRIPTFORMAT : { read(); checkDatabaseUpdateAuthorisation(); switch (token.tokenType) { case Tokens.TEXT : case Tokens.BINARY : case Tokens.COMPRESSED : break; default : throw unexpectedToken(); } int mode = ArrayUtil.find(ScriptWriterBase.LIST_SCRIPT_FORMATS, token.tokenString); if (mode == 0 || mode == 1 || mode == 3) {} else { throw unexpectedToken(); } read(); Object[] args = new Object[]{ new Integer(mode) }; return new StatementCommand( StatementTypes.SET_DATABASE_SCRIPT_FORMAT, args, database.getCatalogName(), null); } case Tokens.IGNORECASE : { read(); boolean mode = processTrueOrFalse(); Object[] args = new Object[]{ Boolean.valueOf(mode) }; return new StatementCommand( StatementTypes.SET_DATABASE_SQL_IGNORECASE, args, null, null); } case Tokens.MAXROWS : { read(); int size = readInteger(); Object[] args = new Object[]{ new Integer(size) }; return new StatementSession( StatementTypes.SET_SESSION_RESULT_MAX_ROWS, args); } // for backward compatibility case Tokens.DEFAULT : { read(); readThis(Tokens.TABLE); readThis(Tokens.TYPE); int type = TableBase.MEMORY_TABLE; switch (token.tokenType) { case Tokens.MEMORY : break; case Tokens.CACHED : type = TableBase.CACHED_TABLE; break; default : throw unexpectedToken(); } read(); Object[] args = new Object[]{ Integer.valueOf(type) }; return new StatementCommand( StatementTypes.SET_DATABASE_DEFAULT_TABLE_TYPE, args, null, null); } case Tokens.RESULT : { read(); readThis(Tokens.MEMORY); readThis(Tokens.SIZE); int size = readInteger(); Object[] args = new Object[]{ new Integer(size) }; return new StatementSession( StatementTypes.SET_SESSION_RESULT_MEMORY_ROWS, args); } case Tokens.TABLE : { read(); Table t = readTableName(); Object[] args = new Object[] { t.tableName, null }; switch (token.tokenType) { default : { throw unexpectedToken(); } case Tokens.SOURCE : read(); return compileTextTableSource(t); case Tokens.READ : { read(); boolean readonly = false; if (token.tokenType == Tokens.WRITE) {} else { readThis(Tokens.ONLY); readonly = true; } args[1] = Boolean.valueOf(readonly); return new StatementCommand( StatementTypes.SET_TABLE_READONLY, args, null, t.getName()); } // deprecated case Tokens.READONLY : { read(); boolean readonly = processTrueOrFalse(); args[1] = Boolean.valueOf(readonly); return new StatementCommand( StatementTypes.SET_TABLE_READONLY, args, null, t.getName()); } case Tokens.INDEX : { String value; read(); checkIsValue(); value = token.tokenString; read(); args[1] = value; return new StatementCommand( StatementTypes.SET_TABLE_INDEX, args, null, null); } case Tokens.TYPE : { read(); int newType; if (token.tokenType == Tokens.CACHED) { newType = TableBase.CACHED_TABLE; } else if (token.tokenType == Tokens.MEMORY) { newType = TableBase.MEMORY_TABLE; } else { throw Error.error(ErrorCode.X_42581); } read(); args[1] = new Integer(newType); return new StatementCommand( StatementTypes.SET_TABLE_TYPE, args, null, t.getName()); } } } case Tokens.CHECKPOINT : { read(); readThis(Tokens.DEFRAG); int size = readInteger(); Object[] args = new Object[]{ new Integer(size) }; return new StatementCommand( StatementTypes.SET_DATABASE_FILES_DEFRAG, args, null, null); } case Tokens.WRITE_DELAY : { read(); int delay = 0; if (token.tokenType == Tokens.TRUE) { delay = database.getProperties().getDefaultWriteDelay(); read(); } else if (token.tokenType == Tokens.FALSE) { delay = 0; read(); } else { delay = this.readInteger(); if (delay < 0) { delay = 0; } if (token.tokenType == Tokens.MILLIS) { read(); } else { delay *= 1000; } } Object[] args = new Object[]{ new Integer(delay) }; return new StatementCommand( StatementTypes.SET_DATABASE_FILES_WRITE_DELAY, args, null, null); } case Tokens.PASSWORD : { String password; read(); password = readPassword(); Object[] args = new Object[] { null, password }; return new StatementCommand(StatementTypes.SET_USER_PASSWORD, args, null, null); } case Tokens.INITIAL : { read(); readThis(Tokens.SCHEMA); HsqlName schema; if (token.tokenType == Tokens.DEFAULT) { schema = null; } else { schema = database.schemaManager.getSchemaHsqlName( token.tokenString); } read(); Object[] args = new Object[] { null, schema }; return new StatementCommand( StatementTypes.SET_USER_INITIAL_SCHEMA, args, null, null); } case Tokens.DATABASE : { read(); String name; switch (token.tokenType) { case Tokens.BACKUP : { read(); checkDatabaseUpdateAuthorisation(); readThis(Tokens.INCREMENT); boolean flag = processTrueOrFalse(); Object[] args = new Object[]{ Boolean.valueOf(flag) }; return new StatementCommand( StatementTypes.SET_DATABASE_FILES_BACKUP_INCREMENT, args, database.getCatalogName(), null); } case Tokens.COLLATION : { read(); checkIsSimpleName(); name = token.tokenString; read(); Object[] args = new Object[]{ name }; return new StatementCommand( StatementTypes.SET_DATABASE_SQL_COLLATION, args, null, null); } case Tokens.DEFAULT : { return compileSetDefault(); } case Tokens.EVENT : { read(); readThis(Tokens.LOG); readThis(Tokens.LEVEL); int value = readInteger(); Object[] args = new Object[]{ Integer.valueOf(value) }; return new StatementCommand( StatementTypes.SET_DATABASE_FILES_EVENT_LOG, args, null, null); } case Tokens.FILES : { read(); int type = 0; boolean flag = false; int value = 0; switch (token.tokenType) { case Tokens.LOCK : { read(); flag = processTrueOrFalse(); type = StatementTypes.SET_DATABASE_FILES_LOCK; break; } case Tokens.READ : { read(); type = StatementTypes .SET_DATABASE_FILES_READ_ONLY; if (readIfThis(Tokens.ONLY)) { flag = true; } else { readThis(Tokens.WRITE); flag = false; } if (readIfThis(Tokens.FILES)) { type = StatementTypes .SET_DATABASE_FILES_READ_ONLY_FILES; } flag = processTrueOrFalse(); break; } case Tokens.CACHE : { read(); if (readIfThis(Tokens.SIZE)) { value = readInteger(); type = StatementTypes .SET_DATABASE_FILES_CACHE_SIZE; } else if (readIfThis(Tokens.ROWS)) { value = readInteger(); type = StatementTypes .SET_DATABASE_FILES_CACHE_FILE_SCALE; } else if (readIfThis(Tokens.FILE)) { readThis(Tokens.SCALE); value = readInteger(); type = StatementTypes .SET_DATABASE_FILES_CACHE_FILE_SCALE; } break; } case Tokens.DEFRAG : { read(); type = StatementTypes .SET_DATABASE_FILES_DEFRAG; value = readInteger(); break; } case Tokens.NIO : { read(); type = StatementTypes.SET_DATABASE_FILES_NIO; flag = processTrueOrFalse(); break; } default : unexpectedToken(); } Object[] args = new Object[] { new Integer(value), Boolean.valueOf(flag) }; return new StatementCommand(type, args, null, null); } case Tokens.REFERENTIAL_INTEGRITY : { read(); boolean mode = processTrueOrFalse(); Object[] args = new Object[]{ Boolean.valueOf(mode) }; return new StatementCommand( StatementTypes .SET_DATABASE_SQL_REFERENTIAL_INTEGRITY, args, null, null); } case Tokens.TRANSACTION : { read(); readThis(Tokens.CONTROL); boolean mvcc = false; if (token.tokenType == Tokens.MVCC) { read(); mvcc = true; } else { readThis(Tokens.LOCKS); } Object[] args = new Object[]{ Boolean.valueOf(mvcc) }; return new StatementCommand( StatementTypes.SET_DATABASE_TRANSACTION_CONTROL, args, null, null); } case Tokens.PROPERTY : { return compileSetProperty(); } default : { throw unexpectedToken(); } } } case Tokens.PROPERTY : { return compileSetProperty(); } default : { rewind(position); return compileSetStatement( session.sessionContext.sessionVariablesRange); } } } Object[] processTransactionCharacteristics() { int level = 0; boolean readonly = false; Object[] args = new Object[2]; outerloop: while (true) { switch (token.tokenType) { case Tokens.READ : { if (args[0] != null) { throw unexpectedToken(); } read(); if (token.tokenType == Tokens.ONLY) { read(); readonly = true; } else { readThis(Tokens.WRITE); readonly = false; } args[0] = Boolean.valueOf(readonly); break; } case Tokens.ISOLATION : { if (args[1] != null) { throw unexpectedToken(); } read(); readThis(Tokens.LEVEL); switch (token.tokenType) { case Tokens.SERIALIZABLE : read(); level = SessionInterface.TX_SERIALIZABLE; break; case Tokens.READ : read(); if (token.tokenType == Tokens.COMMITTED) { read(); level = SessionInterface.TX_READ_COMMITTED; } else if (token.tokenType == Tokens.UNCOMMITTED) { read(); level = SessionInterface.TX_READ_UNCOMMITTED; } else { throw unexpectedToken(); } break; case Tokens.REPEATABLE : read(); readThis(Tokens.READ); level = SessionInterface.TX_REPEATABLE_READ; break; default : throw unexpectedToken(); } args[1] = new Integer(level); break; } default : { break outerloop; } } } if (!readonly && level == 1) { throw unexpectedToken(Tokens.T_WRITE); } return args; } /** * 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() { if (token.tokenType == Tokens.TRUE) { read(); return true; } else if (token.tokenType == Tokens.FALSE) { read(); return false; } else { throw unexpectedToken(); } } /** * Responsible for handling the execution of COMMIT [WORK] * * @throws HsqlException */ private Statement compileCommit() { boolean chain = false; read(); readIfThis(Tokens.WORK); if (token.tokenType == Tokens.AND) { read(); if (token.tokenType == Tokens.NO) { read(); } else { chain = true; } readThis(Tokens.CHAIN); } String sql = getLastPart(); Object[] args = new Object[]{ Boolean.valueOf(chain) }; Statement cs = new StatementSession(StatementTypes.COMMIT_WORK, args); return cs; } private Statement compileStartTransaction() { read(); readThis(Tokens.TRANSACTION); Object[] args = processTransactionCharacteristics(); Statement cs = new StatementSession(StatementTypes.START_TRANSACTION, args); return cs; } private Statement compileLock() { read(); readThis(Tokens.TABLE); OrderedHashSet readSet = new OrderedHashSet(); OrderedHashSet writeSet = new OrderedHashSet(); outerloop: while (true) { Table table = readTableName(); switch (token.tokenType) { case Tokens.READ : read(); readSet.add(table.getName()); break; case Tokens.WRITE : read(); writeSet.add(table.getName()); break; default : throw unexpectedToken(); } if (token.tokenType == Tokens.COMMA) { read(); continue; } break outerloop; } HsqlName[] readTableNames = new HsqlName[readSet.size()]; readSet.toArray(readTableNames); HsqlName[] writeTableNames = new HsqlName[writeSet.size()]; writeSet.toArray(writeTableNames); Statement cs = new StatementSession(StatementTypes.TRANSACTION_LOCK_TABLE, readTableNames, writeTableNames); return cs; } private Statement compileRollback() { boolean chain = false; String savepoint = null; read(); if (token.tokenType == Tokens.TO) { read(); readThis(Tokens.SAVEPOINT); checkIsSimpleName(); savepoint = token.tokenString; read(); String sql = getLastPart(); Object[] args = new Object[]{ savepoint }; Statement cs = new StatementSession(StatementTypes.ROLLBACK_SAVEPOINT, args); return cs; } else { if (token.tokenType == Tokens.WORK) { read(); } if (token.tokenType == Tokens.AND) { read(); if (token.tokenType == Tokens.NO) { read(); } else { chain = true; } readThis(Tokens.CHAIN); } } String sql = getLastPart(); Object[] args = new Object[]{ Boolean.valueOf(chain) }; Statement cs = new StatementSession(StatementTypes.ROLLBACK_WORK, args); return cs; } private Statement compileSavepoint() { String name; read(); checkIsSimpleName(); name = token.tokenString; read(); String sql = getLastPart(); Object[] args = new Object[]{ name }; return new StatementSession(StatementTypes.SAVEPOINT, args); } private Statement compileReleaseSavepoint() { read(); readThis(Tokens.SAVEPOINT); String name = token.tokenString; read(); String sql = getLastPart(); Object[] args = new Object[]{ name }; return new StatementSession(StatementTypes.RELEASE_SAVEPOINT, args); } private Statement compileSessionSettings() { if (token.tokenType == Tokens.CHARACTERISTICS) { read(); readThis(Tokens.AS); Object[] args = processTransactionCharacteristics(); return new StatementSession( StatementTypes.SET_SESSION_CHARACTERISTICS, args); } else if (token.tokenType == Tokens.AUTHORIZATION) { read(); Expression e = XreadValueSpecificationOrNull(); if (e == null) { throw Error.error(ErrorCode.X_42584); } e.resolveTypes(session, null); if (e.isParam()) { e.dataType = Type.SQL_VARCHAR; } if (e.dataType == null || !e.dataType.isCharacterType()) { throw Error.error(ErrorCode.X_42565); } Expression[] args = new Expression[] { e, null }; return new StatementSession( StatementTypes.SET_SESSION_AUTHORIZATION, args); } throw unexpectedToken(); } private Statement compileSetRole() { Expression e; if (token.tokenType == Tokens.NONE) { read(); e = new ExpressionOp(null, Type.SQL_VARCHAR); } else { e = XreadValueSpecificationOrNull(); if (e == null) { throw Error.error(ErrorCode.X_2A000); } if (!e.getDataType().isCharacterType()) { throw Error.error(ErrorCode.X_0P000); } if (e.getType() != OpTypes.VALUE && (e.getType() != OpTypes.SQL_FUNCTION || !((FunctionSQL) e).isValueFunction())) { throw Error.error(ErrorCode.X_0P000); } } String sql = getLastPart(); return new StatementSession(StatementTypes.SET_ROLE, new Expression[]{ e }); } private Statement compileSetTimeZone() { Expression e; readThis(Tokens.ZONE); if (token.tokenType == Tokens.LOCAL) { read(); e = new ExpressionValue(null, Type.SQL_VARCHAR); } else { e = XreadIntervalValueExpression(); HsqlList unresolved = e.resolveColumnReferences(RangeVariable.emptyArray, null); ExpressionColumn.checkColumnsResolved(unresolved); e.resolveTypes(session, null); if (e.dataType == null) { throw Error.error(ErrorCode.X_42565); } if (e.dataType.typeCode != Types.SQL_INTERVAL_HOUR_TO_MINUTE) { throw Error.error(ErrorCode.X_42565); } } String sql = getLastPart(); return new StatementSession(StatementTypes.SET_TIME_ZONE, new Expression[]{ e }); } private Statement compileShutdown() { int closemode; session.checkAdmin(); closemode = Database.CLOSEMODE_NORMAL; read(); switch (token.tokenType) { case Tokens.IMMEDIATELY : closemode = Database.CLOSEMODE_IMMEDIATELY; read(); break; case Tokens.COMPACT : closemode = Database.CLOSEMODE_COMPACT; read(); break; case Tokens.SCRIPT : closemode = Database.CLOSEMODE_SCRIPT; read(); break; // only semicolon is accepted here } if (token.tokenType == Tokens.SEMICOLON) { read(); } if (token.tokenType != Tokens.X_ENDPARSE) { throw unexpectedToken(); } String sql = getLastPart(); Object[] args = new Object[]{ new Integer(closemode) }; Statement cs = new StatementCommand(StatementTypes.DATABASE_SHUTDOWN, args, null, null); return cs; } private Statement compileBackup() { read(); readThis(Tokens.DATABASE); readThis(Tokens.TO); checkIsValue(); readQuotedString(); String path = token.tokenString; read(); Boolean blockingMode = null; // Default to non-blocking Boolean scriptMode = null; // Default to non-script Boolean compression = null; // Defaults to compressed outerLoop: while (true) { switch (token.tokenType) { case Tokens.BLOCKING : if (blockingMode != null) { throw unexpectedToken(); } blockingMode = Boolean.TRUE; read(); break; case Tokens.SCRIPT : if (scriptMode != null) { throw unexpectedToken(); } scriptMode = Boolean.TRUE; read(); break; case Tokens.COMPRESSED : if (compression != null) { throw unexpectedToken(); } compression = Boolean.TRUE; read(); break; case Tokens.NOT : read(); if (token.tokenType == Tokens.COMPRESSED) { if (compression != null) { throw unexpectedToken(); } compression = Boolean.FALSE; read(); } else if (token.tokenType == Tokens.BLOCKING) { blockingMode = Boolean.FALSE; read(); } else { throw unexpectedToken(); } break; default : break outerLoop; } } /** * @todo: This block is TEMPORARY. Will be removed when we implement * Non-Blocking and SCRIPT mode. */ if (scriptMode != null) { throw unsupportedFeature("SCRIPT"); } scriptMode = Boolean.FALSE; if (blockingMode == null) { throw unexpectedTokenRequire("BLOCKING"); } if (compression == null) { compression = Boolean.TRUE; } return new StatementCommand(StatementTypes.DATABASE_BACKUP, new Object[] { path, blockingMode, scriptMode, compression, }, null, null); } private Statement compileCheckpoint() { boolean defrag = false; read(); if (token.tokenType == Tokens.DEFRAG) { defrag = true; read(); } else if (token.tokenType == Tokens.SEMICOLON) { read(); // only semicolon is accepted here } if (token.tokenType != Tokens.X_ENDPARSE) { throw unexpectedToken(); } String sql = getLastPart(); Object[] args = new Object[]{ Boolean.valueOf(defrag) }; HsqlName writeName = defrag ? database.getCatalogName() : null; Statement cs = new StatementCommand(StatementTypes.DATABASE_CHECKPOINT, args, database.getCatalogName(), writeName); return cs; } private Statement compileDisconnect() { read(); String sql = Tokens.T_DISCONNECT; Statement cs = new StatementSession(StatementTypes.DISCONNECT, (Object[]) null); return cs; } private Statement compileExplainPlan() { Statement cs; read(); readThis(Tokens.PLAN); readThis(Tokens.FOR); cs = compilePart(); cs.writeTableNames = HsqlName.emptyArray; cs.readTableNames = HsqlName.emptyArray; cs.setDescribe(); return cs; } private Statement compileTextTableSource(Table t) { boolean isSourceHeader = false; boolean isDesc = false; String source; Object[] args = new Object[5]; args[0] = t.tableName; if (!t.isText()) { Exception e = Error.error(ErrorCode.X_S0522); } // SET TABLE <table> SOURCE ON if (token.tokenType == Tokens.ON) { read(); String sql = getLastPart(); args[1] = Boolean.TRUE; return new StatementCommand(StatementTypes.SET_TABLE_SOURCE, args, null, t.getName()); } else if (token.tokenType == Tokens.OFF) { read(); String sql = getLastPart(); args[1] = Boolean.FALSE; return new StatementCommand(StatementTypes.SET_TABLE_SOURCE, args, null, t.getName()); } else if (token.tokenType == Tokens.HEADER) { read(); isSourceHeader = true; } if (token.tokenType != Tokens.X_DELIMITED_IDENTIFIER && (token.tokenType != Tokens.X_VALUE || !token.dataType.isCharacterType())) { throw Error.error(ErrorCode.X_42581); } source = token.tokenString; read(); if (!isSourceHeader && token.tokenType == Tokens.DESC) { isDesc = true; read(); } String sql = getLastPart(); args[2] = source; args[3] = Boolean.valueOf(isDesc); args[4] = Boolean.valueOf(isSourceHeader); return new StatementCommand(StatementTypes.SET_TABLE_SOURCE, args, null, t.getName()); } }