blob: fb3fc3f6db401f91d249072975ed341d43e7b000 [file] [log] [blame]
/* 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.
*/
package org.hsqldb;
import org.hsqldb.HsqlNameManager.HsqlName;
import org.hsqldb.error.Error;
import org.hsqldb.error.ErrorCode;
import org.hsqldb.lib.HsqlArrayList;
import org.hsqldb.navigator.RowIterator;
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;
import org.hsqldb.types.Type;
/**
* Implementation of Statement for SQL session statements.<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_CATALOG :
case StatementTypes.SET_SESSION_AUTHORIZATION :
case StatementTypes.SET_COLLATION :
group = StatementTypes.X_SQL_SESSION;
break;
default :
throw Error.runtimeError(ErrorCode.U_S0500,
"StateemntSession");
}
}
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_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 :
case StatementTypes.SET_SESSION_SQL_IGNORECASE :
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;
case StatementTypes.DECLARE_SESSION_TABLE :
case StatementTypes.DROP_TABLE :
group = StatementTypes.X_SQL_SESSION;
break;
default :
throw Error.runtimeError(ErrorCode.U_S0500,
"StatementSession");
}
}
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,
"StatementSession");
}
}
public Result execute(Session session) {
Result result;
try {
result = getResult(session);
} catch (Throwable t) {
result = Result.newErrorResult(t, null);
}
if (result.isError()) {
result.getException().setStatementType(group, type);
return result;
}
try {
if (isLogged) {
session.database.logger.writeToLog(session, sql);
}
} catch (Throwable 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);
name = (String) Type.SQL_VARCHAR.trim(session, name, ' ',
true, true);
if (session.database.getCatalogName().name.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.setZoneSeconds(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.setZoneSeconds((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 = null;
try {
name = (String) expressions[0].getValue(session);
if (name != null) {
name = (String) Type.SQL_VARCHAR.trim(session, name,
' ', true, true);
role = session.database.granteeManager.getRole(name);
}
} catch (HsqlException e) {
return Result.newErrorResult(
Error.error(ErrorCode.X_0P000), sql);
}
if (session.isInMidTransaction()) {
return Result.newErrorResult(
Error.error(ErrorCode.X_25001), sql);
}
if (role == null) {
session.setRole(null);
}
if (session.getGrantee().hasRole(role)) {
session.setRole(role);
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);
}
name = (String) Type.SQL_VARCHAR.trim(session, name, ' ',
true, true);
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);
user = (String) Type.SQL_VARCHAR.trim(session, user, ' ',
true, true);
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.setRole(null);
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[] variables = (ColumnSchema[]) parameters[0];
try {
for (int i = 0; i < variables.length; i++) {
session.sessionContext.addSessionVariable(
variables[i]);
}
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;
}
case StatementTypes.SET_SESSION_SQL_IGNORECASE : {
try {
boolean mode = ((Boolean) parameters[0]).booleanValue();
session.setIgnoreCase(mode);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.DECLARE_SESSION_TABLE : {
Table table = (Table) parameters[0];
HsqlArrayList tempConstraints = (HsqlArrayList) parameters[1];
StatementDMQL statement = (StatementDMQL) parameters[2];
try {
if (tempConstraints != null) {
table =
ParserDDL.addTableConstraintDefinitions(session,
table, tempConstraints, null, false);
}
table.compile(session, null);
session.addSessionTable(table);
if (statement != null) {
Result result = statement.execute(session);
table.insertIntoTable(session, result);
}
if (table.hasLobColumn) {
RowIterator it = table.rowIterator(session);
while (it.hasNext()) {
Row row = it.getNextRow();
Object[] data = row.getData();
session.sessionData.adjustLobUsageCount(table,
data, 1);
}
}
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.DROP_TABLE : {
HsqlName name = (HsqlName) parameters[0];
Boolean ifExists = (Boolean) parameters[1];
Table table = session.findSessionTable(name.name);
if (table == null) {
if (ifExists.booleanValue()) {
return Result.updateZeroResult;
} else {
throw Error.error(ErrorCode.X_42501, name.name);
}
}
session.dropSessionTable(name.name);
return Result.updateZeroResult;
}
default :
throw Error.runtimeError(ErrorCode.U_S0500,
"StatementSession");
}
}
public boolean isAutoCommitStatement() {
return false;
}
public String describe(Session session) {
return sql;
}
public boolean isCatalogChange() {
return false;
}
}