/* 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.result.Result; import org.hsqldb.rights.Grantee; import org.hsqldb.rights.User; import org.hsqldb.types.DTIType; import org.hsqldb.types.IntervalSecondData; /** * Implementation of Statement for SQL commands.<p> * * @author Fred Toussi (fredt@users dot sourceforge.net) * @version 1.9.0 * @since 1.9.0 */ public class StatementSession extends Statement { Expression[] expressions; Object[] parameters; StatementSession(int type, Expression[] args) { super(type); this.expressions = args; isTransactionStatement = false; switch (type) { case StatementTypes.SET_PATH : case StatementTypes.SET_TIME_ZONE : case StatementTypes.SET_NAMES : case StatementTypes.SET_ROLE : case StatementTypes.SET_SCHEMA : case StatementTypes.SET_SESSION_AUTHORIZATION : case StatementTypes.SET_COLLATION : group = StatementTypes.X_SQL_SESSION; break; default : throw Error.runtimeError(ErrorCode.U_S0500, "StateemntCommand"); } } StatementSession(int type, Object[] args) { super(type); this.parameters = args; isTransactionStatement = false; isLogged = false; switch (type) { // logged by statement case StatementTypes.SET_SCHEMA : group = StatementTypes.X_SQL_SESSION; isLogged = true; break; case StatementTypes.DECLARE_VARIABLE : group = StatementTypes.X_HSQLDB_SESSION; isLogged = true; break; // cursor case StatementTypes.ALLOCATE_CURSOR : group = StatementTypes.X_SQL_DATA; break; case StatementTypes.ALLOCATE_DESCRIPTOR : case StatementTypes.DEALLOCATE_DESCRIPTOR : case StatementTypes.DEALLOCATE_PREPARE : group = StatementTypes.X_DYNAMIC; break; // case StatementTypes.DYNAMIC_DELETE_CURSOR : group = StatementTypes.X_SQL_DATA_CHANGE; break; case StatementTypes.DYNAMIC_CLOSE : case StatementTypes.DYNAMIC_FETCH : case StatementTypes.DYNAMIC_OPEN : group = StatementTypes.X_SQL_DATA; break; // case StatementTypes.OPEN : case StatementTypes.FETCH : case StatementTypes.FREE_LOCATOR : case StatementTypes.GET_DESCRIPTOR : case StatementTypes.HOLD_LOCATOR : group = StatementTypes.X_SQL_DATA; break; // case StatementTypes.PREPARABLE_DYNAMIC_DELETE_CURSOR : case StatementTypes.PREPARABLE_DYNAMIC_UPDATE_CURSOR : case StatementTypes.PREPARE : group = StatementTypes.X_DYNAMIC; break; // logged by session case StatementTypes.DISCONNECT : group = StatementTypes.X_SQL_CONNECTION; break; // case StatementTypes.SET_CONNECTION : case StatementTypes.SET_CONSTRAINT : case StatementTypes.SET_DESCRIPTOR : case StatementTypes.SET_CATALOG : case StatementTypes.SET_SESSION_CHARACTERISTICS : case StatementTypes.SET_TRANSFORM_GROUP : case StatementTypes.SET_SESSION_RESULT_MAX_ROWS : case StatementTypes.SET_SESSION_RESULT_MEMORY_ROWS : case StatementTypes.SET_SESSION_AUTOCOMMIT : group = StatementTypes.X_HSQLDB_SESSION; break; // logged by session if necessary case StatementTypes.COMMIT_WORK : case StatementTypes.RELEASE_SAVEPOINT : case StatementTypes.ROLLBACK_SAVEPOINT : case StatementTypes.ROLLBACK_WORK : case StatementTypes.SAVEPOINT : case StatementTypes.SET_TRANSACTION : case StatementTypes.START_TRANSACTION : group = StatementTypes.X_SQL_TRANSACTION; break; default : throw Error.runtimeError(ErrorCode.U_S0500, "StatementCommand"); } } StatementSession(int type, HsqlName[] readNames, HsqlName[] writeNames) { super(type); this.isTransactionStatement = true; this.readTableNames = readNames; writeTableNames = writeNames; switch (type) { case StatementTypes.TRANSACTION_LOCK_TABLE : group = StatementTypes.X_HSQLDB_TRANSACTION; break; default : throw Error.runtimeError(ErrorCode.U_S0500, "StatementCommand"); } } public Result execute(Session session) { Result result = getResult(session); if (result.isError()) { result.getException().setStatementType(group, type); return result; } try { if (isLogged) { session.database.logger.writeToLog(session, sql); } } catch (HsqlException e) { return Result.newErrorResult(e, sql); } return result; } Result getResult(Session session) { boolean startTransaction = false; if (this.isExplain) { return Result.newSingleColumnStringResult("OPERATION", describe(session)); } switch (type) { // cursor case StatementTypes.ALLOCATE_CURSOR : case StatementTypes.ALLOCATE_DESCRIPTOR : return Result.updateZeroResult; // case StatementTypes.COMMIT_WORK : { try { boolean chain = parameters != null; session.commit(chain); return Result.updateZeroResult; } catch (HsqlException e) { return Result.newErrorResult(e, sql); } } case StatementTypes.DEALLOCATE_DESCRIPTOR : case StatementTypes.DEALLOCATE_PREPARE : return Result.updateZeroResult; case StatementTypes.DISCONNECT : session.close(); return Result.updateZeroResult; // case StatementTypes.DYNAMIC_CLOSE : case StatementTypes.DYNAMIC_DELETE_CURSOR : case StatementTypes.DYNAMIC_FETCH : case StatementTypes.DYNAMIC_OPEN : // case StatementTypes.FETCH : case StatementTypes.FREE_LOCATOR : case StatementTypes.GET_DESCRIPTOR : case StatementTypes.HOLD_LOCATOR : // case StatementTypes.OPEN : case StatementTypes.PREPARABLE_DYNAMIC_DELETE_CURSOR : case StatementTypes.PREPARABLE_DYNAMIC_UPDATE_CURSOR : case StatementTypes.PREPARE : return Result.updateZeroResult; case StatementTypes.TRANSACTION_LOCK_TABLE : { return Result.updateZeroResult; } case StatementTypes.RELEASE_SAVEPOINT : { String savepoint = (String) parameters[0]; try { session.releaseSavepoint(savepoint); return Result.updateZeroResult; } catch (HsqlException e) { return Result.newErrorResult(e, sql); } } case StatementTypes.ROLLBACK_WORK : { boolean chain = ((Boolean) parameters[0]).booleanValue(); session.rollback(chain); return Result.updateZeroResult; } case StatementTypes.ROLLBACK_SAVEPOINT : { String savepoint = (String) parameters[0]; try { session.rollbackToSavepoint(savepoint); return Result.updateZeroResult; } catch (HsqlException e) { return Result.newErrorResult(e, sql); } } case StatementTypes.SAVEPOINT : { String savepoint = (String) parameters[0]; session.savepoint(savepoint); return Result.updateZeroResult; } case StatementTypes.SET_CATALOG : { String name; try { name = (String) expressions[0].getValue(session); if (session.database.getCatalogName().equals(name)) { return Result.updateZeroResult; } return Result.newErrorResult( Error.error(ErrorCode.X_3D000), sql); } catch (HsqlException e) { return Result.newErrorResult(e, sql); } } case StatementTypes.SET_CONNECTION : case StatementTypes.SET_CONSTRAINT : case StatementTypes.SET_DESCRIPTOR : return Result.updateZeroResult; case StatementTypes.SET_TIME_ZONE : { Object value = null; if (expressions[0].getType() == OpTypes.VALUE && expressions[0].getConstantValueNoCheck(session) == null) { session.timeZoneSeconds = session.sessionTimeZoneSeconds; return Result.updateZeroResult; } try { value = expressions[0].getValue(session); } catch (HsqlException e) {} if (value instanceof Result) { Result result = (Result) value; if (result.isData()) { Object[] data = (Object[]) result.getNavigator().getNext(); boolean single = !result.getNavigator().next(); if (single && data != null && data[0] != null) { value = data[0]; result.getNavigator().close(); } else { result.getNavigator().close(); return Result.newErrorResult( Error.error(ErrorCode.X_22009), sql); } } else { return Result.newErrorResult( Error.error(ErrorCode.X_22009), sql); } } else { if (value == null) { return Result.newErrorResult( Error.error(ErrorCode.X_22009), sql); } } long seconds = ((IntervalSecondData) value).getSeconds(); if (-DTIType.timezoneSecondsLimit <= seconds && seconds <= DTIType.timezoneSecondsLimit) { session.timeZoneSeconds = (int) seconds; return Result.updateZeroResult; } return Result.newErrorResult(Error.error(ErrorCode.X_22009), sql); } case StatementTypes.SET_NAMES : return Result.updateZeroResult; case StatementTypes.SET_PATH : return Result.updateZeroResult; case StatementTypes.SET_ROLE : { String name; Grantee role; try { name = (String) expressions[0].getValue(session); role = session.database.granteeManager.getRole(name); } catch (HsqlException e) { return Result.newErrorResult( Error.error(ErrorCode.X_0P000), sql); } if (role == null) { return Result.newErrorResult( Error.error(ErrorCode.X_0P000), sql); } if (session.getGrantee().hasRole(role)) { /** @todo 1.9.0 - implement */ return Result.updateZeroResult; } else { return Result.newErrorResult( Error.error(ErrorCode.X_0P000), sql); } } case StatementTypes.SET_SCHEMA : { String name; HsqlName schema; try { if (expressions == null) { name = ((HsqlName) parameters[0]).name; } else { name = (String) expressions[0].getValue(session); } schema = session.database.schemaManager.getSchemaHsqlName(name); session.setSchema(schema.name); return Result.updateZeroResult; } catch (HsqlException e) { return Result.newErrorResult(e, sql); } } case StatementTypes.SET_SESSION_AUTHORIZATION : { if (session.isInMidTransaction()) { return Result.newErrorResult( Error.error(ErrorCode.X_25001), sql); } try { String user; String password = null; user = (String) expressions[0].getValue(session); if (expressions[1] != null) { password = (String) expressions[1].getValue(session); } User userObject; if (password == null) { userObject = session.database.userManager.get(user); } else { userObject = session.database.getUserManager().getUser(user, password); } if (userObject == null) { throw Error.error(ErrorCode.X_28501); } sql = userObject.getConnectUserSQL(); if (userObject == session.getGrantee()) { return Result.updateZeroResult; } if (session.getGrantee().canChangeAuthorisation()) { session.setUser((User) userObject); session.resetSchema(); return Result.updateZeroResult; } /** @todo may need different error code */ throw Error.error(ErrorCode.X_28000); } catch (HsqlException e) { return Result.newErrorResult(e, sql); } } case StatementTypes.SET_SESSION_CHARACTERISTICS : { try { if (parameters[0] != null) { boolean readonly = ((Boolean) parameters[0]).booleanValue(); session.setReadOnlyDefault(readonly); } if (parameters[1] != null) { int level = ((Integer) parameters[1]).intValue(); session.setIsolationDefault(level); } return Result.updateZeroResult; } catch (HsqlException e) { return Result.newErrorResult(e, sql); } } case StatementTypes.SET_COLLATION : return Result.updateZeroResult; case StatementTypes.SET_TRANSFORM_GROUP : return Result.updateZeroResult; case StatementTypes.START_TRANSACTION : startTransaction = true; // fall through case StatementTypes.SET_TRANSACTION : { try { if (parameters[0] != null) { boolean readonly = ((Boolean) parameters[0]).booleanValue(); session.setReadOnly(readonly); } if (parameters[1] != null) { int level = ((Integer) parameters[1]).intValue(); session.setIsolation(level); } if (startTransaction) { session.startTransaction(); } return Result.updateZeroResult; } catch (HsqlException e) { return Result.newErrorResult(e, sql); } } // case StatementTypes.SET_SESSION_AUTOCOMMIT : { boolean mode = ((Boolean) parameters[0]).booleanValue(); try { session.setAutoCommit(mode); return Result.updateZeroResult; } catch (HsqlException e) { return Result.newErrorResult(e, sql); } } case StatementTypes.DECLARE_VARIABLE : { ColumnSchema variable = (ColumnSchema) parameters[0]; try { session.sessionContext.addSessionVariable(variable); return Result.updateZeroResult; } catch (HsqlException e) { return Result.newErrorResult(e, sql); } } case StatementTypes.SET_SESSION_RESULT_MAX_ROWS : { int size = ((Integer) parameters[0]).intValue(); session.setSQLMaxRows(size); return Result.updateZeroResult; } case StatementTypes.SET_SESSION_RESULT_MEMORY_ROWS : { int size = ((Integer) parameters[0]).intValue(); session.setResultMemoryRowCount(size); return Result.updateZeroResult; } default : throw Error.runtimeError(ErrorCode.U_S0500, "CompiledStateemntCommand"); } } public boolean isAutoCommitStatement() { return false; } public String describe(Session session) { return sql; } }