/* 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.java.JavaSystem;
import org.hsqldb.persist.HsqlDatabaseProperties;
import org.hsqldb.persist.HsqlProperties;
import org.hsqldb.result.Result;
import org.hsqldb.rights.User;
import org.hsqldb.scriptio.ScriptWriterText;
/**
* 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 StatementCommand extends Statement {
Expression[] expressions;
Object[] parameters;
StatementCommand(int type, Object[] args) {
this(type, args, null, null);
}
StatementCommand(int type, Object[] args, HsqlName readName,
HsqlName writeName) {
super(type);
this.isTransactionStatement = true;
this.parameters = args;
if (readName != null && readName != writeName) {
this.readTableNames = new HsqlName[]{ readName };
}
if (writeName != null) {
this.writeTableNames = new HsqlName[]{ writeName };
}
switch (type) {
case StatementTypes.DATABASE_CHECKPOINT :
group = StatementTypes.X_HSQLDB_DATABASE_OPERATION;
isLogged = false;
break;
case StatementTypes.DATABASE_BACKUP :
case StatementTypes.DATABASE_SCRIPT :
group = StatementTypes.X_HSQLDB_DATABASE_OPERATION;
isLogged = false;
break;
case StatementTypes.SET_DATABASE_UNIQUE_NAME :
case StatementTypes.SET_DATABASE_FILES_WRITE_DELAY :
case StatementTypes.SET_DATABASE_FILES_TEMP_PATH :
this.isTransactionStatement = false;
group = StatementTypes.X_HSQLDB_SETTING;
break;
//
case StatementTypes.SET_DATABASE_DEFAULT_INITIAL_SCHEMA :
case StatementTypes.SET_DATABASE_DEFAULT_TABLE_TYPE :
case StatementTypes.SET_DATABASE_FILES_CACHE_ROWS :
case StatementTypes.SET_DATABASE_FILES_CACHE_SIZE :
case StatementTypes.SET_DATABASE_FILES_SCALE :
case StatementTypes.SET_DATABASE_FILES_DEFRAG :
case StatementTypes.SET_DATABASE_FILES_EVENT_LOG :
case StatementTypes.SET_DATABASE_FILES_LOBS_SCALE :
case StatementTypes.SET_DATABASE_FILES_LOCK :
case StatementTypes.SET_DATABASE_FILES_LOG :
case StatementTypes.SET_DATABASE_FILES_LOG_SIZE :
case StatementTypes.SET_DATABASE_FILES_NIO :
case StatementTypes.SET_DATABASE_FILES_SCRIPT_FORMAT :
case StatementTypes.SET_DATABASE_PROPERTY :
case StatementTypes.SET_DATABASE_RESULT_MEMORY_ROWS :
case StatementTypes.SET_DATABASE_SQL_REFERENTIAL_INTEGRITY :
case StatementTypes.SET_DATABASE_SQL_STRICT_NAMES :
case StatementTypes.SET_DATABASE_SQL_STRICT_SIZE :
case StatementTypes.SET_DATABASE_SQL_REFERENCES :
case StatementTypes.SET_DATABASE_TRANSACTION_CONTROL :
case StatementTypes.SET_DATABASE_DEFAULT_ISOLATION_LEVEL :
case StatementTypes.SET_DATABASE_GC :
//
case StatementTypes.SET_DATABASE_SQL_COLLATION :
case StatementTypes.SET_DATABASE_FILES_BACKUP_INCREMENT :
case StatementTypes.SET_DATABASE_SCRIPT_FORMAT :
case StatementTypes.SET_DATABASE_TEXT_SOURCE :
group = StatementTypes.X_HSQLDB_SETTING;
this.isTransactionStatement = true;
break;
case StatementTypes.SET_TABLE_SOURCE_HEADER :
isLogged = false;
case StatementTypes.SET_TABLE_SOURCE :
metaDataImpact = Statement.META_RESET_VIEWS;
group = StatementTypes.X_HSQLDB_SCHEMA_MANIPULATION;
this.isTransactionStatement = true;
break;
case StatementTypes.SET_TABLE_READONLY :
metaDataImpact = Statement.META_RESET_VIEWS;
group = StatementTypes.X_HSQLDB_SCHEMA_MANIPULATION;
this.isTransactionStatement = true;
break;
case StatementTypes.DATABASE_SHUTDOWN :
isLogged = false;
group = StatementTypes.X_HSQLDB_DATABASE_OPERATION;
this.isTransactionStatement = false;
break;
case StatementTypes.SET_TABLE_TYPE :
group = StatementTypes.X_HSQLDB_SCHEMA_MANIPULATION;
this.isTransactionStatement = true;
break;
case StatementTypes.SET_TABLE_INDEX :
group = StatementTypes.X_HSQLDB_SETTING;
this.isTransactionStatement = false;
isLogged = false;
break;
case StatementTypes.SET_USER_INITIAL_SCHEMA :
case StatementTypes.SET_USER_PASSWORD :
group = StatementTypes.X_HSQLDB_SETTING;
this.isTransactionStatement = false;
break;
default :
throw Error.runtimeError(ErrorCode.U_S0500,
"StatementCommand");
}
}
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) {
if (this.isExplain) {
return Result.newSingleColumnStringResult("OPERATION",
describe(session));
}
switch (type) {
case StatementTypes.DATABASE_BACKUP : {
String path = ((String) parameters[0]);
boolean blocking = ((Boolean) parameters[1]).booleanValue();
boolean script = ((Boolean) parameters[2]).booleanValue();
boolean compressed = ((Boolean) parameters[3]).booleanValue();
try {
session.checkAdmin();
if (!session.database.getType().equals(
DatabaseURL.S_FILE)) {
// Do not enforce this constraint for SCRIPT type
// backup.
return Result.newErrorResult(
Error.error(ErrorCode.DATABASE_IS_NON_FILE));
// If we were to back up res: type DB's, could use
// DatabasURL.isFileBasedDataType(), but I see no
// point to back up one of these.
}
if (session.database.isReadOnly()) {
// Do not enforce this constraint for SCRIPT type
// backup.
return Result.newErrorResult(
Error.error(ErrorCode.DATABASE_IS_MEMORY_ONLY),
null);
}
if (session.database.logger.isStoredFileAccess) {
return Result.newErrorResult(
Error.error(ErrorCode.DATABASE_IS_NON_FILE), null);
}
session.database.logger.backup(path,
session.database.getPath(),
script, blocking,
compressed);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.DATABASE_CHECKPOINT : {
boolean defrag = ((Boolean) parameters[0]).booleanValue();
try {
session.database.logger.checkpoint(defrag);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_FILES_BACKUP_INCREMENT : {
try {
boolean mode = ((Boolean) parameters[0]).booleanValue();
session.checkAdmin();
session.checkDDLWrite();
session.database.logger.setIncrementBackup(mode);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_FILES_CACHE_ROWS : {
try {
int value = ((Integer) parameters[0]).intValue();
session.checkAdmin();
session.checkDDLWrite();
session.database.logger.setCacheMaxRows(value);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_FILES_CACHE_SIZE : {
try {
int value = ((Integer) parameters[0]).intValue();
session.checkAdmin();
session.checkDDLWrite();
session.database.logger.setCacheSize(value);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_FILES_LOBS_SCALE : {
try {
int value = ((Integer) parameters[0]).intValue();
session.checkAdmin();
session.checkDDLWrite();
if (session.isProcessingScript) {
session.database.logger.setLobFileScaleNoCheck(value);
} else {
session.database.logger.setLobFileScale(value);
}
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_FILES_SCALE : {
try {
int value = ((Integer) parameters[0]).intValue();
session.checkAdmin();
session.checkDDLWrite();
if (session.isProcessingScript) {
session.database.logger.setCacheFileScaleNoCheck(value);
} else {
session.database.logger.setCacheFileScale(value);
}
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_FILES_DEFRAG : {
try {
int value = ((Integer) parameters[0]).intValue();
session.checkAdmin();
session.checkDDLWrite();
session.database.logger.setDefagLimit(value);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_FILES_EVENT_LOG : {
try {
int value = ((Integer) parameters[0]).intValue();
session.checkAdmin();
session.checkDDLWrite();
session.database.logger.setEventLogLevel(value);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_FILES_LOCK : {
try {
// no-op - to remove from release version
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_FILES_NIO : {
try {
boolean value = ((Boolean) parameters[0]).booleanValue();
session.checkAdmin();
session.checkDDLWrite();
session.database.logger.setNioDataFile(value);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_FILES_LOG : {
try {
boolean value = ((Boolean) parameters[0]).booleanValue();
session.checkAdmin();
session.checkDDLWrite();
session.database.logger.setLogData(value);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_FILES_LOG_SIZE : {
try {
int value = ((Integer) parameters[0]).intValue();
session.checkAdmin();
session.checkDDLWrite();
session.database.logger.setLogSize(value);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_FILES_TEMP_PATH : {
try {
String value = (String) parameters[0];
session.checkAdmin();
session.checkDDLWrite();
// no action
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_FILES_WRITE_DELAY : {
try {
int value = ((Integer) parameters[0]).intValue();
session.checkAdmin();
session.checkDDLWrite();
session.database.logger.setWriteDelay(value);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_SQL_COLLATION : {
try {
String name = (String) parameters[0];
/** @todo 1.9.0 - ensure no data in character columns */
session.checkAdmin();
session.checkDDLWrite();
session.database.collation.setCollation(name);
session.database.schemaManager.setSchemaChangeTimestamp();
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_SQL_REFERENTIAL_INTEGRITY : {
boolean mode = ((Boolean) parameters[0]).booleanValue();
session.database.setReferentialIntegrity(mode);
return Result.updateZeroResult;
}
case StatementTypes.SET_DATABASE_SQL_STRICT_NAMES : {
boolean mode = ((Boolean) parameters[0]).booleanValue();
session.database.setStrictNames(mode);
return Result.updateZeroResult;
}
case StatementTypes.SET_DATABASE_SQL_STRICT_SIZE : {
boolean mode = ((Boolean) parameters[0]).booleanValue();
session.database.setStrictColumnSize(mode);
return Result.updateZeroResult;
}
case StatementTypes.SET_DATABASE_SQL_REFERENCES : {
boolean mode = ((Boolean) parameters[0]).booleanValue();
session.database.setStrictReferences(mode);
return Result.updateZeroResult;
}
case StatementTypes.SET_DATABASE_DEFAULT_INITIAL_SCHEMA : {
HsqlName schema = (HsqlName) parameters[0];
//
session.database.schemaManager.setDefaultSchemaHsqlName(
schema);
session.database.schemaManager.setSchemaChangeTimestamp();
//
return Result.updateZeroResult;
}
case StatementTypes.SET_DATABASE_DEFAULT_TABLE_TYPE : {
Integer type = (Integer) parameters[0];
//
session.database.schemaManager.setDefaultTableType(
type.intValue());
//
return Result.updateZeroResult;
}
case StatementTypes.SET_DATABASE_SCRIPT_FORMAT : {
try {
int value = ((Integer) parameters[0]).intValue();
session.checkAdmin();
session.checkDDLWrite();
session.database.logger.setScriptType(value);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_TRANSACTION_CONTROL : {
try {
int mode = ((Integer) parameters[0]).intValue();
session.checkAdmin();
session.checkDDLWrite();
session.database.txManager.setTransactionControl(session,
mode);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_DEFAULT_ISOLATION_LEVEL : {
try {
int mode = ((Integer) parameters[0]).intValue();
session.checkAdmin();
session.checkDDLWrite();
session.database.defaultIsolationLevel = mode;
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_GC : {
try {
int count = ((Integer) parameters[0]).intValue();
session.checkAdmin();
JavaSystem.gcFrequency = count;
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_PROPERTY : {
try {
String property = (String) parameters[0];
Object value = parameters[1];
// command is a no-op from 1.9
session.checkAdmin();
session.checkDDLWrite();
/*
HsqlDatabaseProperties p =
session.database.getProperties();
p.setDatabaseProperty(property,
value.toString().toLowerCase());
*/
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_RESULT_MEMORY_ROWS : {
int size = ((Integer) parameters[0]).intValue();
session.database.getProperties().setProperty(
HsqlDatabaseProperties.hsqldb_result_max_memory_rows,
size);
session.database.setResultMaxMemoryRows(size);
return Result.updateZeroResult;
}
case StatementTypes.SET_DATABASE_TEXT_SOURCE : {
try {
String source = (String) parameters[0];
HsqlProperties props = null;
if (source.length() > 0) {
props = HsqlProperties.delimitedArgPairsToProps(source,
"=", ";", null);
if (props.getErrorKeys().length > 0) {
throw Error.error(ErrorCode.TEXT_TABLE_SOURCE,
props.getErrorKeys()[0]);
}
}
session.database.logger.setDefaultTextTableProperties(
source, props);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_DATABASE_UNIQUE_NAME : {
try {
String name = (String) parameters[0];
session.database.setUniqueName(name);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.DATABASE_SCRIPT : {
ScriptWriterText dsw = null;
String name = (String) parameters[0];
if (name == null) {
return session.database.getScript(false);
} else {
try {
dsw = new ScriptWriterText(session.database, name,
true, true, true);
dsw.writeAll();
dsw.close();
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
return Result.updateZeroResult;
}
}
case StatementTypes.DATABASE_SHUTDOWN : {
try {
int mode = ((Integer) parameters[0]).intValue();
session.database.close(mode);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_TABLE_INDEX : {
try {
HsqlName name = (HsqlName) parameters[0];
String value = (String) parameters[1];
Table table =
session.database.schemaManager.getTable(session,
name.name, name.schema.name);
table.setIndexRoots(session, value);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_TABLE_READONLY : {
try {
HsqlName name = (HsqlName) parameters[0];
Table table =
session.database.schemaManager.getTable(session,
name.name, name.schema.name);
boolean mode = ((Boolean) parameters[1]).booleanValue();
session.checkAdmin();
session.checkDDLWrite();
table.setDataReadOnly(mode);
session.database.schemaManager.setSchemaChangeTimestamp();
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_TABLE_SOURCE :
case StatementTypes.SET_TABLE_SOURCE_HEADER : {
try {
HsqlName name = (HsqlName) parameters[0];
Table table =
session.database.schemaManager.getTable(session,
name.name, name.schema.name);
if (!table.isText()) {
Exception e = Error.error(ErrorCode.X_S0522);
return Result.newErrorResult(e, sql);
}
if (parameters[1] != null) {
boolean mode =
((Boolean) parameters[1]).booleanValue();
if (mode) {
((TextTable) table).connect(session);
} else {
((TextTable) table).disconnect();
}
session.database.schemaManager.setSchemaChangeTimestamp();
return Result.updateZeroResult;
}
String source = (String) parameters[2];
boolean isDesc = ((Boolean) parameters[3]).booleanValue();
boolean isHeader =
((Boolean) parameters[4]).booleanValue();
if (isHeader) {
((TextTable) table).setHeader(source);
} else {
((TextTable) table).setDataSource(session, source,
isDesc, false);
}
return Result.updateZeroResult;
} catch (Throwable e) {
if (!(e instanceof HsqlException)) {
e = Error.error(ErrorCode.GENERAL_IO_ERROR,
e.getMessage());
}
if (session.isProcessingLog()
|| session.isProcessingScript()) {
session.addWarning((HsqlException) e);
session.database.logger.logWarningEvent(
"Problem processing SET TABLE SOURCE", e);
return Result.updateZeroResult;
} else {
return Result.newErrorResult(e, sql);
}
}
}
case StatementTypes.SET_TABLE_TYPE : {
try {
HsqlName name = (HsqlName) parameters[0];
int type = ((Integer) parameters[1]).intValue();
//
session.checkAdmin();
session.checkDDLWrite();
Table table =
session.database.schemaManager.getUserTable(session,
name.name, name.schema.name);
session.setScripting(true);
TableWorks tw = new TableWorks(session, table);
tw.setTableType(session, type);
session.database.schemaManager.setSchemaChangeTimestamp();
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_USER_INITIAL_SCHEMA : {
try {
User user = (User) parameters[0];
HsqlName schema = (HsqlName) parameters[1];
session.checkDDLWrite();
if (user == null) {
user = session.getUser();
} else {
session.checkAdmin();
session.checkDDLWrite();
user = session.database.userManager.get(
user.getNameString());
}
if (schema != null) {
schema =
session.database.schemaManager.getSchemaHsqlName(
schema.name);
}
//
user.setInitialSchema(schema);
session.database.schemaManager.setSchemaChangeTimestamp();
//
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
case StatementTypes.SET_USER_PASSWORD : {
try {
User user = parameters[0] == null ? session.getUser()
: (User) parameters[0];
String password = (String) parameters[1];
session.checkDDLWrite();
session.setScripting(true);
user.setPassword(password);
return Result.updateZeroResult;
} catch (HsqlException e) {
return Result.newErrorResult(e, sql);
}
}
default :
throw Error.runtimeError(ErrorCode.U_S0500, "StatemntCommand");
}
}
public boolean isAutoCommitStatement() {
return isTransactionStatement;
}
public String describe(Session session) {
return sql;
}
}