📄 session.java
字号:
/*
* Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.engine;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import org.h2.command.Command;
import org.h2.command.CommandInterface;
import org.h2.command.Parser;
import org.h2.command.Prepared;
import org.h2.command.dml.SetTypes;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.jdbc.JdbcConnection;
import org.h2.log.InDoubtTransaction;
import org.h2.log.LogSystem;
import org.h2.log.UndoLog;
import org.h2.log.UndoLogRecord;
import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.message.TraceSystem;
import org.h2.result.LocalResult;
import org.h2.result.Row;
import org.h2.schema.Schema;
import org.h2.store.DataHandler;
import org.h2.table.Table;
import org.h2.util.ObjectArray;
import org.h2.util.ObjectUtils;
import org.h2.value.Value;
import org.h2.value.ValueLob;
import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
/**
* A session represents a database connection. When using the server mode, this
* object resides on the server side and communicates with a RemoteSession on
* the client side.
*/
public class Session implements SessionInterface {
private User user;
private int id;
private Database database;
private ObjectArray locks = new ObjectArray();
private UndoLog undoLog;
private boolean autoCommit = true;
private Random random;
private LogSystem logSystem;
private int lockTimeout;
private Value lastIdentity = ValueLong.get(0);
private int firstUncommittedLog = LogSystem.LOG_WRITTEN;
private int firstUncommittedPos = LogSystem.LOG_WRITTEN;
private HashMap savepoints;
private Exception stackTrace = new Exception();
private HashMap localTempTables;
private int throttle;
private long lastThrottle;
private Command currentCommand;
private boolean allowLiterals;
private String currentSchemaName;
private String[] schemaSearchPath;
private String traceModuleName;
private HashMap unlinkMap;
private int tempViewIndex;
private HashMap procedures;
private static int nextSerialId;
private int serialId = nextSerialId++;
private boolean undoLogEnabled = true;
private boolean autoCommitAtTransactionEnd;
private String currentTransactionName;
private volatile long cancelAt;
private boolean closed;
private boolean rollbackMode;
private long sessionStart = System.currentTimeMillis();
private long currentCommandStart;
private HashMap variables;
private HashSet temporaryResults;
private int queryTimeout = SysProperties.getMaxQueryTimeout();
private int lastUncommittedDelete;
private boolean commitOrRollbackDisabled;
public Session() {
}
public boolean setCommitOrRollbackDisabled(boolean x) {
boolean old = commitOrRollbackDisabled;
commitOrRollbackDisabled = x;
return old;
}
private void initVariables() {
if (variables == null) {
variables = new HashMap();
}
}
public void setVariable(String name, Value value) throws SQLException {
initVariables();
Value old;
if (value == ValueNull.INSTANCE) {
old = (Value) variables.remove(name);
} else {
if (value instanceof ValueLob) {
// link it, to make sure we have our own file
value = value.link(database, ValueLob.TABLE_ID_SESSION);
}
old = (Value) variables.put(name, value);
}
if (old != null) {
// close the old value (in case it is a lob)
old.unlink();
old.close();
}
}
public Value getVariable(String name) {
initVariables();
Value v = (Value) variables.get(name);
return v == null ? ValueNull.INSTANCE : v;
}
public Table findLocalTempTable(String name) {
Table t = null;
if (localTempTables != null) {
t = (Table) localTempTables.get(name);
}
return t;
}
public ObjectArray getLocalTempTables() {
if (localTempTables == null) {
return new ObjectArray();
}
ObjectArray list = new ObjectArray(localTempTables.values());
return list;
}
public void addLocalTempTable(Table table) throws SQLException {
if (localTempTables == null) {
localTempTables = new HashMap();
}
if (localTempTables.get(table.getName()) != null) {
throw Message.getSQLException(ErrorCode.TABLE_OR_VIEW_ALREADY_EXISTS_1, table.getSQL());
}
localTempTables.put(table.getName(), table);
}
public void removeLocalTempTable(Table table) throws SQLException {
localTempTables.remove(table.getName());
table.removeChildrenAndResources(this);
}
protected void finalize() {
if (!SysProperties.runFinalize) {
return;
}
if (!closed) {
throw Message.getInternalError("not closed", stackTrace);
}
}
public boolean getAutoCommit() {
return autoCommit;
}
public User getUser() {
return user;
}
public void setAutoCommit(boolean b) {
autoCommit = b;
}
public int getLockTimeout() {
return lockTimeout;
}
public void setLockTimeout(int lockTimeout) {
this.lockTimeout = lockTimeout;
}
public SessionInterface createSession(ConnectionInfo ci) throws SQLException {
return Engine.getInstance().getSession(ci);
}
Session(Database database, User user, int id) {
this.database = database;
this.undoLog = new UndoLog(this);
this.user = user;
this.id = id;
this.logSystem = database.getLog();
Setting setting = database.findSetting(SetTypes.getTypeName(SetTypes.DEFAULT_LOCK_TIMEOUT));
this.lockTimeout = setting == null ? Constants.INITIAL_LOCK_TIMEOUT : setting.getIntValue();
this.currentSchemaName = Constants.SCHEMA_MAIN;
}
public CommandInterface prepareCommand(String sql, int fetchSize) throws SQLException {
return prepareLocal(sql);
}
public Prepared prepare(String sql) throws SQLException {
return prepare(sql, false);
}
public Prepared prepare(String sql, boolean rightsChecked) throws SQLException {
Parser parser = new Parser(this);
parser.setRightsChecked(rightsChecked);
return parser.prepare(sql);
}
public Command prepareLocal(String sql) throws SQLException {
if (closed) {
throw Message.getSQLException(ErrorCode.CONNECTION_BROKEN);
}
Parser parser = new Parser(this);
return parser.prepareCommand(sql);
}
public Database getDatabase() {
return database;
}
public int getPowerOffCount() {
return database.getPowerOffCount();
}
public void setPowerOffCount(int count) {
database.setPowerOffCount(count);
}
public int getLastUncommittedDelete() {
return lastUncommittedDelete;
}
public void setLastUncommittedDelete(int deleteId) {
lastUncommittedDelete = deleteId;
}
public void commit(boolean ddl) throws SQLException {
checkCommitRollback();
lastUncommittedDelete = 0;
currentTransactionName = null;
if (containsUncommitted()) {
// need to commit even if rollback is not possible
// (create/drop table and so on)
logSystem.commit(this);
}
if (undoLog.size() > 0) {
if (database.isMultiVersion()) {
ArrayList rows = new ArrayList();
synchronized (database) {
while (undoLog.size() > 0) {
UndoLogRecord entry = undoLog.getAndRemoveLast();
entry.commit();
rows.add(entry.getRow());
}
for (int i = 0; i < rows.size(); i++) {
Row r = (Row) rows.get(i);
r.commit();
}
}
}
undoLog.clear();
}
if (!ddl) {
// do not clean the temp tables if the last command was a
// create/drop
cleanTempTables(false);
if (autoCommitAtTransactionEnd) {
autoCommit = true;
autoCommitAtTransactionEnd = false;
}
}
if (unlinkMap != null && unlinkMap.size() > 0) {
// need to flush the log file, because we can't unlink lobs if the
// commit record is not written
logSystem.flush();
Iterator it = unlinkMap.values().iterator();
while (it.hasNext()) {
Value v = (Value) it.next();
v.unlink();
}
unlinkMap = null;
}
unlockAll();
}
private void checkCommitRollback() throws SQLException {
if (commitOrRollbackDisabled && locks.size() > 0) {
throw Message.getSQLException(ErrorCode.COMMIT_ROLLBACK_NOT_ALLOWED);
}
}
public void rollback() throws SQLException {
checkCommitRollback();
currentTransactionName = null;
boolean needCommit = false;
if (undoLog.size() > 0) {
rollbackTo(0);
needCommit = true;
}
if (locks.size() > 0 || needCommit) {
logSystem.commit(this);
}
cleanTempTables(false);
unlockAll();
if (autoCommitAtTransactionEnd) {
autoCommit = true;
autoCommitAtTransactionEnd = false;
}
}
public void rollbackTo(int index) throws SQLException {
while (undoLog.size() > index) {
UndoLogRecord entry = undoLog.getAndRemoveLast();
rollbackMode = true;
try {
entry.undo(this);
} finally {
rollbackMode = false;
}
}
if (savepoints != null) {
String[] names = new String[savepoints.size()];
savepoints.keySet().toArray(names);
for (int i = 0; i < names.length; i++) {
String name = names[i];
Integer id = (Integer) savepoints.get(names[i]);
if (id.intValue() > index) {
savepoints.remove(name);
}
}
}
}
public int getLogId() {
return undoLog.size();
}
public int getId() {
return id;
}
public void cancel() {
cancelAt = System.currentTimeMillis();
}
public void close() throws SQLException {
if (!closed) {
try {
cleanTempTables(true);
database.removeSession(this);
} finally {
closed = true;
}
}
}
public void addLock(Table table) {
if (SysProperties.CHECK) {
if (locks.indexOf(table) >= 0) {
throw Message.getInternalError();
}
}
locks.add(table);
}
/**
* Add an undo log entry to this session.
*
* @param table the table
* @param type the operation type (see {@link UndoLogRecord})
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -