org.hsqldb.persist.ScriptRunner Maven / Gradle / Ivy
Show all versions of sqltool Show documentation
/* Copyright (c) 2001-2020, 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.persist;
import java.io.EOFException;
import org.hsqldb.Database;
import org.hsqldb.HsqlException;
import org.hsqldb.HsqlNameManager.HsqlName;
import org.hsqldb.Row;
import org.hsqldb.Session;
import org.hsqldb.Statement;
import org.hsqldb.StatementDML;
import org.hsqldb.StatementTypes;
import org.hsqldb.Table;
import org.hsqldb.error.Error;
import org.hsqldb.error.ErrorCode;
import org.hsqldb.lib.IntKeyHashMap;
import org.hsqldb.map.ValuePool;
import org.hsqldb.result.Result;
import org.hsqldb.scriptio.ScriptReaderBase;
import org.hsqldb.scriptio.ScriptReaderDecode;
import org.hsqldb.scriptio.ScriptReaderText;
import org.hsqldb.scriptio.StatementLineTypes;
/**
* Restores the state of a Database instance from an SQL log file.
*
* If there is an error, processing stops at that line and the message is
* logged to the application log. If memory runs out, an exception is thrown.
*
* @author Fred Toussi (fredt@users dot sourceforge.net)
* @version 2.5.1
* @since 1.7.2
*/
public class ScriptRunner {
/**
* This is used to read the *.log file and manage any necessary
* transaction rollback.
*/
public static void runScript(Database database, String logFilename,
boolean fullReplay) {
Crypto crypto = database.logger.getCrypto();
ScriptReaderBase scr;
try {
if (crypto == null) {
scr = new ScriptReaderText(database, logFilename, false);
} else {
scr = new ScriptReaderDecode(database, logFilename, crypto,
true);
}
} catch (Throwable e) {
// catch out-of-memory errors and terminate
if (e instanceof EOFException) {
// end of file - normal end
} else {
// stop processing on bad script line
database.logger.logSevereEvent("opening log file", e);
}
return;
}
runScript(database, scr, fullReplay);
}
private static void runScript(Database database, ScriptReaderBase scr,
boolean fullReplay) {
IntKeyHashMap sessionMap = new IntKeyHashMap();
Session current = null;
int currentId = 0;
String statement;
int statementType;
Statement dummy = new StatementDML(StatementTypes.UPDATE_CURSOR, null);
String databaseFile = database.getCanonicalPath();
String action = fullReplay ? "open aborted"
: "open continued";
dummy.setCompileTimestamp(Long.MAX_VALUE);
database.setReferentialIntegrity(false);
try {
while (scr.readLoggedStatement(current)) {
int sessionId = scr.getSessionNumber();
if (current == null || currentId != sessionId) {
currentId = sessionId;
current = (Session) sessionMap.get(currentId);
if (current == null) {
// note the sessionId does not match the sessionId of
// new session
current =
database.getSessionManager().newSessionForLog(
database);
sessionMap.put(currentId, current);
}
}
Result result = null;
statementType = scr.getStatementType();
switch (statementType) {
case StatementLineTypes.SET_FILES_CHECK_STATEMENT :
result = null;
// fall through
case StatementLineTypes.ANY_STATEMENT :
statement = scr.getLoggedStatement();
Statement cs;
try {
cs = current.compileStatement(statement);
result = current.executeCompiledStatement(cs,
ValuePool.emptyObjectArray, 0);
} catch (Throwable e) {
result = Result.newErrorResult(e);
}
if (result != null && result.isError()) {
if (result.getException() != null) {
throw result.getException();
}
throw Error.error(result);
}
break;
case StatementLineTypes.COMMIT_STATEMENT :
current.commit(false);
break;
case StatementLineTypes.INSERT_STATEMENT : {
current.sessionContext.currentStatement = dummy;
current.beginAction(dummy);
Object[] data = scr.getData();
scr.getCurrentTable().insertNoCheckFromLog(current,
data);
current.endAction(Result.updateOneResult);
break;
}
case StatementLineTypes.DELETE_STATEMENT : {
current.sessionContext.currentStatement = dummy;
current.beginAction(dummy);
Table table = scr.getCurrentTable();
PersistentStore store = table.getRowStore(current);
Object[] data = scr.getData();
Row row = table.getDeleteRowFromLog(current, data);
if (row != null) {
current.addDeleteAction(table, store, row, null);
}
current.endAction(Result.updateOneResult);
break;
}
case StatementLineTypes.SET_SCHEMA_STATEMENT : {
HsqlName name =
database.schemaManager.findSchemaHsqlName(
scr.getCurrentSchema());
current.setCurrentSchemaHsqlName(name);
break;
}
case StatementLineTypes.SESSION_ID : {
break;
}
default :
throw Error.error(ErrorCode.ERROR_IN_LOG_FILE);
}
if (current.isClosed()) {
current = null;
sessionMap.remove(currentId);
}
}
} catch (HsqlException e) {
if (e.getErrorCode() == -ErrorCode.ERROR_IN_LOG_FILE) {
throw e;
}
// stop processing on bad log line
String error = "statement error processing log - " + action + " "
+ scr.getFileNamePath() + " line: "
+ scr.getLineNumber();
database.logger.logSevereEvent(error, e);
if (fullReplay) {
throw Error.error(e, ErrorCode.ERROR_IN_LOG_FILE, error);
}
} catch (OutOfMemoryError e) {
String error = "out of memory processing log - " + databaseFile
+ " line: " + scr.getLineNumber();
// catch out-of-memory errors and terminate
database.logger.logSevereEvent(error, e);
throw Error.error(ErrorCode.OUT_OF_MEMORY);
} catch (Throwable t) {
HsqlException e =
Error.error(t, ErrorCode.ERROR_IN_LOG_FILE,
ErrorCode.M_DatabaseScriptReader_read,
new String[] {
scr.getLineNumber() + " " + databaseFile, t.getMessage()
});
// stop processing on bad script line
String error = "statement error processing log - " + action
+ scr.getFileNamePath() + " line: "
+ scr.getLineNumber();
database.logger.logSevereEvent(error, e);
if (fullReplay) {
throw e;
}
} finally {
if (scr != null) {
scr.close();
}
database.getSessionManager().closeAllSessions();
database.setReferentialIntegrity(true);
}
}
}