/** add session to the end of queue when a transaction starts (depending on isolation mode) */ public void beginAction(Session session, Statement cs) { synchronized (liveTransactionTimestamps) { session.actionTimestamp = nextChangeTimestamp(); if (!session.isTransaction) { session.transactionTimestamp = session.actionTimestamp; session.isTransaction = true; liveTransactionTimestamps.addLast(session.actionTimestamp); } } if (session.hasLocks()) { return; } try { writeLock.lock(); boolean canProceed = beginActionTPL(session, cs); if (!canProceed) { session.abortTransaction = true; } } finally { writeLock.unlock(); } }
/** add session to the end of queue when a transaction starts (depending on isolation mode) */ public void beginAction(Session session, Statement cs) { if (session.hasLocks(cs)) { return; } writeLock.lock(); try { if (cs.getCompileTimestamp() < database.schemaManager.getSchemaChangeTimestamp()) { cs = session.statementManager.getStatement(session, cs); session.sessionContext.currentStatement = cs; if (cs == null) { return; } } boolean canProceed = setWaitedSessionsTPL(session, cs); if (canProceed) { if (session.tempSet.isEmpty()) { lockTablesTPL(session, cs); // we don't set other sessions that would now be waiting for this one too } else { setWaitingSessionTPL(session); } } else { session.abortTransaction = true; } } finally { writeLock.unlock(); } }
/** * Drops the index with the specified name from this database. * * @param indexname the name of the index to drop * @param ifExists if true and if the Index to drop does not exist, fail silently, else throw * @param session the execution context * @throws HsqlException if the index does not exist, the session lacks the permission or the * operation violates database integrity */ void dropIndex(Session session, String indexname, String tableName, boolean ifExists) throws HsqlException { Table t = findUserTableForIndex(session, indexname); if (t == null) { if (ifExists) { return; } else { throw Trace.error(Trace.INDEX_NOT_FOUND, indexname); } } if (tableName != null && !t.getName().name.equals(tableName)) { throw Trace.error(Trace.INDEX_NOT_FOUND, indexname); } t.checkDropIndex(indexname, null); // fredt@users 20020405 - patch 1.7.0 by fredt - drop index bug // see Table.moveDefinition(); session.commit(); session.setScripting(!t.isTemp()); TableWorks tw = new TableWorks(session, t); tw.dropIndex(indexname); }
/** * Retrieves the <code>User</code> objects representing the database users that are visible to the * <code>User</code> object represented by the <code>session</code> argument. * * <p>If the <code>session</code> argument's <code>User</code> object attribute has isAdmin() true * (directly or by virtue of a Role), then all of the <code>User</code> objects in this collection * are considered visible. Otherwise, only this object's special <code>PUBLIC</code> <code>User * </code> object attribute and the session <code>User</code> object, if it exists in this * collection, are considered visible. * * <p> * * @param session The <code>Session</code> object used to determine visibility * @return a list of <code>User</code> objects visible to the <code>User</code> object contained * by the <code>session</code> argument. */ public HsqlArrayList listVisibleUsers(Session session) { HsqlArrayList list; User user; boolean isAdmin; String sessionName; String userName; list = new HsqlArrayList(); isAdmin = session.isAdmin(); sessionName = session.getUsername(); if (userList == null || userList.size() == 0) { return list; } for (int i = 0; i < userList.size(); i++) { user = (User) userList.get(i); if (user == null) { continue; } userName = user.getName().getNameString(); if (isAdmin) { list.add(user); } else if (sessionName.equals(userName)) { list.add(user); } } return list; }
public void readLobResults( SessionInterface session, DataInputStream inputStream, RowInputBinary in) throws IOException, HsqlException { Result currentResult = this; boolean hasLob = false; setSession(session); while (true) { int addedResultMode = inputStream.readByte(); if (addedResultMode == ResultConstants.LARGE_OBJECT_OP) { ResultLob resultLob = ResultLob.newLob(inputStream, false); if (session instanceof Session) { ((Session) session).allocateResultLob(resultLob, inputStream); } else { currentResult.addLobResult(resultLob); } hasLob = true; continue; } else if (addedResultMode == ResultConstants.NONE) { break; } else { throw Error.runtimeError(ErrorCode.U_S0500, "Result"); } } if (hasLob) { ((Session) session).registerResultLobs(currentResult); } }
public void run() { try { for (int i = sessionList.size() - 1; i >= 0; i--) { Session session = (Session) sessionList.get(i); if (session.isClosed()) { synchronized (this) { sessionList.remove(i); } continue; } boolean result = session.timeoutManager.checkTimeout(); /* if (result) { synchronized (this) { sessionList.remove(i); } } */ } } catch (Throwable e) { // ignore exceptions // may be InterruptedException or IOException } }
public boolean commitTransaction(Session session) { if (session.abortTransaction) { return false; } int limit = session.rowActionList.size(); Object[] list = session.rowActionList.getArray(); writeLock.lock(); try { // new actionTimestamp used for commitTimestamp session.actionTimestamp = nextChangeTimestamp(); session.transactionEndTimestamp = session.actionTimestamp; endTransaction(session); for (int i = 0; i < limit; i++) { RowAction action = (RowAction) list[i]; action.commit(session); } persistCommit(session, list, limit); int newLimit = session.rowActionList.size(); if (newLimit > limit) { list = session.rowActionList.getArray(); mergeTransaction(session, list, limit, newLimit, session.actionTimestamp); finaliseRows(session, list, limit, newLimit, true); session.rowActionList.setSize(limit); } // session.actionTimestamp is the committed tx timestamp if (getFirstLiveTransactionTimestamp() > session.actionTimestamp || session == lobSession) { mergeTransaction(session, list, 0, limit, session.actionTimestamp); finaliseRows(session, list, 0, limit, true); } else { list = session.rowActionList.toArray(); addToCommittedQueue(session, list); } endTransactionTPL(session); } finally { writeLock.unlock(); } session.tempSet.clear(); return true; }
public void beginTransaction(Session session) { synchronized (liveTransactionTimestamps) { session.actionTimestamp = nextChangeTimestamp(); session.transactionTimestamp = session.actionTimestamp; session.isTransaction = true; liveTransactionTimestamps.addLast(session.transactionTimestamp); } }
/** * Executes an UPDATE statement. It is assumed that the argument is of the correct type. * * @param cs a CompiledStatement of type CompiledStatement.UPDATE * @throws HsqlException if a database access error occurs * @return the result of executing the statement */ private Result executeUpdateStatement(CompiledStatement cs) throws HsqlException { Table table = cs.targetTable; TableFilter filter = cs.tf; int count = 0; if (filter.findFirst()) { int[] colmap = cs.columnMap; // column map Expression[] colvalues = cs.columnValues; Expression condition = cs.condition; // update condition int len = colvalues.length; HashMappedList rowset = new HashMappedList(); int size = table.getColumnCount(); int[] coltypes = table.getColumnTypes(); boolean success = false; do { if (condition == null || condition.test(session)) { try { Row row = filter.currentRow; Object[] ni = table.getNewRow(); System.arraycopy(row.getData(), 0, ni, 0, size); for (int i = 0; i < len; i++) { int ci = colmap[i]; ni[ci] = colvalues[i].getValue(session, coltypes[ci]); } rowset.add(row, ni); } catch (HsqlInternalException e) { } } } while (filter.next()); session.beginNestedTransaction(); try { count = table.update(session, rowset, colmap); success = true; } finally { // update failed (constraint violation) or succeeded session.endNestedTransaction(!success); } } updateResult.iUpdateCount = count; return updateResult; }
public void rollback(Session session) { session.abortTransaction = false; session.actionTimestamp = nextChangeTimestamp(); rollbackPartial(session, 0, session.transactionTimestamp); endTransaction(session); try { writeLock.lock(); endTransactionTPL(session); } finally { writeLock.unlock(); } }
/** * Drops the specified user-defined view or table from this Database object. * * <p>The process of dropping a table or view includes: * * <OL> * <LI>checking that the specified Session's currently connected User has the right to perform * this operation and refusing to proceed if not by throwing. * <LI>checking for referential constraints that conflict with this operation and refusing to * proceed if they exist by throwing. * <LI>removing the specified Table from this Database object. * <LI>removing any exported foreign keys Constraint objects held by any tables referenced by * the table to be dropped. This is especially important so that the dropped Table ceases to * be referenced, eventually allowing its full garbage collection. * <LI> * </OL> * * <p> * * @param name of the table or view to drop * @param ifExists if true and if the Table to drop does not exist, fail silently, else throw * @param isView true if the name argument refers to a View * @param session the connected context in which to perform this operation * @throws HsqlException if any of the checks listed above fail */ void dropTable(Session session, String name, boolean ifExists, boolean isView) throws HsqlException { Table toDrop = null; int dropIndex = -1; for (int i = 0; i < tTable.size(); i++) { toDrop = (Table) tTable.get(i); if (toDrop.equals(session, name) && isView == toDrop.isView()) { dropIndex = i; break; } else { toDrop = null; } } if (dropIndex == -1) { if (ifExists) { return; } else { throw Trace.error(isView ? Trace.VIEW_NOT_FOUND : Trace.TABLE_NOT_FOUND, name); } } if (!toDrop.isTemp()) { session.checkDDLWrite(); } if (isView) { checkViewIsInView((View) toDrop); } else { checkTableIsReferenced(toDrop); checkTableIsInView(toDrop.tableName.name); } tTable.remove(dropIndex); removeExportedKeys(toDrop); userManager.removeDbObject(toDrop.getName()); triggerNameList.removeOwner(toDrop.tableName); indexNameList.removeOwner(toDrop.tableName); constraintNameList.removeOwner(toDrop.tableName); toDrop.dropTriggers(); toDrop.drop(); session.setScripting(!toDrop.isTemp()); session.commit(); }
protected void readExistingData(Session session) throws IOException, HsqlException { for (; ; ) { String s = readTableInit(); if (s == null) { break; } String schema = session.getSchemaName(currentSchema); Table t = db.schemaManager.getUserTable(session, s, schema); int j = 0; for (j = 0; ; j++) { if (readRow(t) == false) { break; } } int checkCount = readTableTerm(); if (j != checkCount) { throw Trace.error( Trace.ERROR_IN_SCRIPT_FILE, Trace.ERROR_IN_BINARY_SCRIPT_1, new Object[] {s, new Integer(j), new Integer(checkCount)}); } } }
/** Instantiate this as a SET statement. */ StatementSet( Session session, Table table, RangeVariable rangeVars[], int[] updateColumnMap, Expression[] colExpressions, CompileContext compileContext) { super( StatementTypes.ASSIGNMENT, StatementTypes.X_SQL_DATA_CHANGE, session.getCurrentSchemaHsqlName()); this.operationType = TRIGGER_SET; this.targetTable = table; this.baseTable = targetTable.getBaseTable(); this.updateColumnMap = updateColumnMap; this.updateExpressions = colExpressions; this.updateCheckColumns = targetTable.getColumnCheckList(updateColumnMap); this.targetRangeVariables = rangeVars; isTransactionStatement = false; setDatabseObjects(compileContext); checkAccessRights(session); }
public Result execute(Session session) { Result result; if (targetTable != null && session.isReadOnly() && !targetTable.isTemp()) { HsqlException e = Error.error(ErrorCode.X_25006); return Result.newErrorResult(e); } if (isExplain) { return getExplainResult(session); } try { if (subqueries.length > 0) { materializeSubQueries(session); } result = getResult(session); } catch (Throwable t) { result = Result.newErrorResult(t, null); result.getException().setStatementType(group, type); } session.sessionContext.clearStructures(this); return result; }
/** Initializes this connection. */ private void init() { runnerThread = Thread.currentThread(); keepAlive = true; try { socket.setTcpNoDelay(true); dataInput = new DataInputStream(socket.getInputStream()); dataOutput = new BufferedOutputStream(socket.getOutputStream()); Result resultIn = Result.read(rowIn, dataInput); Result resultOut; try { int dbIndex = ArrayUtil.find(server.dbAlias, resultIn.subSubString); dbID = server.dbID[dbIndex]; user = resultIn.getMainString(); password = resultIn.getSubString(); if (!server.isSilent()) { server.printWithThread(mThread + ":trying to connect user " + user); } session = DatabaseManager.newSession(dbID, resultIn.getMainString(), resultIn.getSubString()); resultOut = new Result(ResultConstants.UPDATECOUNT); resultOut.databaseID = session.getDatabase().databaseID; resultOut.sessionID = session.getId(); } catch (HsqlException e) { session = null; resultOut = new Result(e, null); } catch (ArrayIndexOutOfBoundsException e) { session = null; resultOut = new Result(Trace.error(Trace.DATABASE_NOT_EXISTS), resultIn.subSubString); } Result.write(resultOut, rowOut, dataOutput); return; } catch (Exception e) { server.printWithThread(mThread + ":couldn't connect " + user); } close(); }
public void run() { try { Session sysSession = sessionManager.newSysSession(); Statement checkpoint = ParserCommand.getAutoCheckpointStatement(Database.this); sysSession.executeCompiledStatement(checkpoint, ValuePool.emptyObjectArray, 0); sysSession.commit(false); sysSession.close(); waiting = false; } catch (Throwable e) { // ignore exceptions // may be InterruptedException or IOException } }
Node getRoot(Session session) { if (isTemp) { return session.getIndexRoot(indexName, onCommitPreserve); } else { return root; } }
void setRoot(Session session, Node node) { if (isTemp) { session.setIndexRoot(indexName, onCommitPreserve, node); } else { root = node; } }
// result Result getDataResultHead(Result command, Result result, boolean isNetwork) { int fetchSize = command.getFetchSize(); result.setResultId(session.actionTimestamp); if (command.rsConcurrency == ResultConstants.CONCUR_READ_ONLY) { result.setDataResultConcurrency(ResultConstants.CONCUR_READ_ONLY); result.setDataResultHoldability(command.rsHoldability); } else { if (result.rsConcurrency == ResultConstants.CONCUR_READ_ONLY) { result.setDataResultHoldability(command.rsHoldability); // add warning for concurrency conflict } else { if (session.isAutoCommit()) { result.setDataResultConcurrency(ResultConstants.CONCUR_READ_ONLY); result.setDataResultHoldability(ResultConstants.HOLD_CURSORS_OVER_COMMIT); } else { result.setDataResultHoldability(ResultConstants.CLOSE_CURSORS_AT_COMMIT); } } } result.setDataResultScrollability(command.rsScrollability); boolean hold = false; boolean copy = false; if (result.rsConcurrency == ResultConstants.CONCUR_UPDATABLE) { hold = true; } if (isNetwork) { if (fetchSize != 0 && result.getNavigator().getSize() > fetchSize) { copy = true; hold = true; } } else { if (result.getNavigator().isDiskBased()) { hold = true; } } if (hold) { if (resultMap == null) { resultMap = new LongKeyHashMap(); } resultMap.put(result.getResultId(), result); } if (copy) { result = Result.newDataHeadResult(session, result, 0, fetchSize); } return result; }
/** Initializes this connection. */ private void init() { runnerThread = Thread.currentThread(); keepAlive = true; try { socket.setTcpNoDelay(true); dataInput = new DataInputStream(new BufferedInputStream(socket.getInputStream())); dataOutput = new BufferedOutputStream(socket.getOutputStream()); Result resultIn = Result.read(rowIn, dataInput); Result resultOut; try { dbID = server.getDBID(resultIn.subSubString); user = resultIn.getMainString(); password = resultIn.getSubString(); if (!server.isSilent()) { server.printWithThread(mThread + ":trying to connect user " + user); } session = DatabaseManager.newSession(dbID, resultIn.getMainString(), resultIn.getSubString()); resultOut = new Result(ResultConstants.UPDATECOUNT); resultOut.databaseID = session.getDatabase().databaseID; resultOut.sessionID = session.getId(); } catch (HsqlException e) { session = null; resultOut = new Result(e, null); } catch (RuntimeException e) { session = null; resultOut = new Result(e, null); } Result.write(resultOut, rowOut, dataOutput); return; } catch (Exception e) { server.printWithThread(mThread + ":couldn't connect " + user); } close(); }
public boolean prepareCommitActions(Session session) { Object[] list = session.rowActionList.getArray(); int limit = session.rowActionList.size(); if (session.abortTransaction) { // System.out.println("cascade fail " + session + " " + session.actionTimestamp); return false; } try { writeLock.lock(); for (int i = 0; i < limit; i++) { RowAction rowact = (RowAction) list[i]; if (!rowact.canCommit(session, session.tempSet)) { // System.out.println("commit conflicts " + session + " " + // session.actionTimestamp); return false; } } session.actionTimestamp = nextChangeTimestamp(); for (int i = 0; i < limit; i++) { RowAction action = (RowAction) list[i]; action.prepareCommit(session); } for (int i = 0; i < session.tempSet.size(); i++) { Session current = (Session) session.tempSet.get(i); current.abortTransaction = true; } return true; } finally { writeLock.unlock(); session.tempSet.clear(); } }
public void beginTransaction(Session session) { writeLock.lock(); try { if (!session.isTransaction) { session.actionTimestamp = nextChangeTimestamp(); session.transactionTimestamp = session.actionTimestamp; session.isTransaction = true; transactionCount++; liveTransactionTimestamps.addLast(session.transactionTimestamp); } } finally { writeLock.unlock(); } }
/** * Executes an INSERT_SELECT statement. It is assumed that the argument is of the correct type. * * @param cs a CompiledStatement of type CompiledStatement.INSERT_SELECT * @throws HsqlException if a database access error occurs * @return the result of executing the statement */ private Result executeInsertSelectStatement(CompiledStatement cs) throws HsqlException { Table t = cs.targetTable; Select s = cs.select; int[] ct = t.getColumnTypes(); // column types Result r = s.getResult(session.getMaxRows(), session); Record rc = r.rRoot; int[] cm = cs.columnMap; // column map boolean[] ccl = cs.checkColumns; // column check list int len = cm.length; Object[] row; int count; boolean success = false; session.beginNestedTransaction(); try { while (rc != null) { row = t.getNewRowData(session, ccl); for (int i = 0; i < len; i++) { int j = cm[i]; if (ct[j] != r.metaData.colType[i]) { row[j] = Column.convertObject(rc.data[i], ct[j]); } else { row[j] = rc.data[i]; } } rc.data = row; rc = rc.next; } count = t.insert(session, r); success = true; } finally { session.endNestedTransaction(!success); } updateResult.iUpdateCount = count; return updateResult; }
/** * The main SQL statement executor. * * <p>All requests to execute SQL statements against this Database object eventually go through * this method. * * @param statement the SQL statement to execute * @param session an object representing a connected user and a collection of session state * attributes * @return the result of executing the specified statement, in a form suitable for either wrapping * in a local ResultSet object or for transmitting to a remote client via the native HSQLDB * protocol * @deprecated from 1.7.2; Session is now the HSQLDB execution hub */ Result execute(String statement, Session session) { try { Trace.check(session != null, Trace.ACCESS_IS_DENIED); } catch (SQLException e) { return new Result(e, statement); } return session.sqlExecuteDirect(statement); }
/** * Drops the index with the specified name from this database. * * @param indexname the name of the index to drop * @param session the execution context * @throws SQLException if the index does not exist, the session lacks the permission or the * operation violates database integrity */ void dropIndex(String indexname, Session session) throws SQLException { Table t = findUserTableForIndex(indexname, session); if (t == null) { throw Trace.error(Trace.INDEX_NOT_FOUND, indexname); } t.checkDropIndex(indexname, null); // fredt@users 20020405 - patch 1.7.0 by fredt - drop index bug // see Table.moveDefinition(); session.commit(); session.setScripting(!t.isTemp()); TableWorks tw = new TableWorks(t); tw.dropIndex(indexname); }
Result getWriteAccessResult(Session session) { try { if (targetTable != null && !targetTable.isTemp()) { session.checkReadWrite(); } } catch (HsqlException e) { return Result.newErrorResult(e); } return null; }
/** Drops a trigger with the specified name in the given context. */ void dropTrigger(Session session, String name) throws HsqlException { boolean found = triggerNameList.containsName(name); Trace.check(found, Trace.TRIGGER_NOT_FOUND, name); HsqlName tableName = (HsqlName) triggerNameList.removeName(name); Table t = this.findUserTable(session, tableName.name); t.dropTrigger(name); session.setScripting(!t.isTemp()); }
/** Drops from this Database any temporary tables owned by the specified Session. */ void dropTempTables(Session ownerSession) { int i = tTable.size(); while (i-- > 0) { Table toDrop = (Table) tTable.get(i); if (toDrop.isTemp() && toDrop.getOwnerSessionId() != ownerSession.getId()) { tTable.remove(i); } } }
/** * Executes a SELECT statement. It is assumed that the argument is of the correct type. * * @param cs a CompiledStatement of type CompiledStatement.SELECT * @throws HsqlException if a database access error occurs * @return the result of executing the statement */ private Result executeSelectStatement(CompiledStatement cs) throws HsqlException { Select select = cs.select; Result result; if (select.sIntoTable != null) { // session level user rights session.checkDDLWrite(); if (session.getDatabase().findUserTable(session, select.sIntoTable.name) != null || session.getDatabase().dInfo.getSystemTable(session, select.sIntoTable.name) != null) { throw Trace.error(Trace.TABLE_ALREADY_EXISTS, select.sIntoTable.name); } result = select.getResult(session.getMaxRows(), session); result = session.dbCommandInterpreter.processSelectInto( result, select.sIntoTable, select.intoType); session.getDatabase().setMetaDirty(false); } else { result = select.getResult(session.getMaxRows(), session); } return result; }
void endTransactionTPL(Session session) { int unlockedCount = 0; unlockTablesTPL(session); final int waitingCount = session.waitingSessions.size(); if (waitingCount == 0) { return; } for (int i = 0; i < waitingCount; i++) { Session current = (Session) session.waitingSessions.get(i); current.tempUnlocked = false; long count = current.latch.getCount(); if (count == 1) { boolean canProceed = setWaitedSessionsTPL(current, current.currentStatement); if (!canProceed) { current.abortTransaction = true; } if (current.tempSet.isEmpty()) { lockTablesTPL(current, current.currentStatement); current.tempUnlocked = true; unlockedCount++; } } } for (int i = 0; i < waitingCount; i++) { Session current = (Session) session.waitingSessions.get(i); if (!current.tempUnlocked) { // this can introduce additional waits for the sessions boolean canProceed = setWaitedSessionsTPL(current, current.currentStatement); if (!canProceed) { current.abortTransaction = true; } } } for (int i = 0; i < waitingCount; i++) { Session current = (Session) session.waitingSessions.get(i); setWaitingSessionTPL(current); } session.tempSet.clear(); session.waitingSessions.clear(); }