/// <summary> /// Ends the given <c>HsqlTransaction</c> with either /// a commit or rollback. /// </summary> /// <param name="transaction">The transaction to end.</param> /// <param name="commit"> /// When <c>true</c> then commit; else rollback. /// </param> internal void EndTransactionInternal(HsqlTransaction transaction, bool commit) { // sanity check if (transaction == null) { throw new ArgumentNullException("transaction"); } // We need to make a local reference now, so we can tentatively // set the instance field to null, but set it back if things go // wrong, for instance a transient network partition is in effect // that may revert shortly, or an integrity constraint condition // that cannot presently be satisfied may also shortly be rectified. HsqlTransaction localTransaction = m_transaction; // sanity check if (transaction != localTransaction) { throw new InvalidOperationException( "Not issued on this connection: " + transaction); // NOI18N } // anticipate success m_transaction = null; try { // Important: // // Access session via the Session property, so we puke if, // for some reason, this connection is closed or is not in // a valid state HsqlSession session = Session; if (commit) { session.Commit(); } else { session.Rollback(); } // Important: only if commit/rollback succeeds. session.AutoCommit = true; } catch /*(Exception ex)*/ { // Failure may only be temporary, so don't leave // things hanging in limbo. Instead, provide for // the possibility that we might want to retry the // operation. m_transaction = localTransaction; throw; } // Prevent further use of transaction object: localTransaction.DisposeInternal(/*rollback*/ false); }
private void OpenSessionNoTimeout() { SetStateInternal(ConnectionState.Connecting); try { m_session = HsqlDriver.GetSession(m_settings); SetStateInternal(ConnectionState.Open); #if SYSTRAN if (m_settings.Enlist) { Transaction tx = Transaction.Current; if (tx != null) { EnlistTransaction(tx); } } #endif } catch (Exception) { m_session = null; SetStateInternal(ConnectionState.Closed); throw; } }
/// <summary> /// Begins a new transaction with the specified isolation level. /// </summary> /// <param name="isolationLevel"> /// The isolation level. /// </param> /// <returns> /// An object representing the new transaction. /// </returns> /// <exception cref="HsqlDataSourceException"> /// When database access error occurs, sql session is closed /// or isolation level not supported. /// </exception> internal HsqlTransaction BeginTransactionInternal( IsolationLevel isolationLevel) { HsqlTransaction transaction = m_transaction; if (transaction != null) { throw new HsqlDataSourceException( "A transaction is already in progress."); // NOI18N } // Note: property read access includes closed check. HsqlSession session = Session; if (isolationLevel == IsolationLevel.Unspecified) { isolationLevel = IsolationLevel.ReadUncommitted; } // Note: property write access includes validation check session.IsolationLevel = isolationLevel; session.AutoCommit = false; transaction = new HsqlTransaction(this, isolationLevel); m_transaction = transaction; return(transaction); }
/// <summary> /// Tests if this connection is closed, throwing an exception if it is. /// </summary> /// <exception cref="InvalidOperationException"> /// When this connection is closed. /// </exception> private void CheckClosed() { // normal check. if (m_connectionState == ConnectionState.Closed) { throw new InvalidOperationException( "Connection is closed."); // NOI18N } // sanity check. HsqlSession session = m_session; if (session == null || session.IsClosed()) { throw new InvalidOperationException( "Connection is closed."); // NOI18N } }
void OpenSessionTimeout(int timeout) { Exception se = null; Thread thread = new Thread(delegate() { try { OpenSessionNoTimeout(); } catch (Exception ex) { se = ex; } }); try { thread.Start(); thread.Join(timeout); } catch (Exception) { m_session = null; SetStateInternal(ConnectionState.Closed); throw; } if (se != null) { m_session = null; SetStateInternal(ConnectionState.Closed); throw se; } else if (m_session == null) { SetStateInternal(ConnectionState.Closed); throw new TimeoutException(string.Format( "Connection attempt aborted after {0} milliseconds", (timeout == Threading.Timeout.Infinite) ? "Infinite" : timeout.ToString("N"))); } }
/// <summary> /// Provides the core logic for the <see cref="Prepare()"/> method. /// </summary> internal void PrepareInternal() { if (!IsPrepared) { string sql; HsqlSession session = this.Session; switch (m_commandType) { case CommandType.StoredProcedure: { sql = StoredProcedureCommandText; break; } case CommandType.Text: { sql = DefaultParameterMarkerCommandText; break; } case CommandType.TableDirect: { sql = TableDirectCommandText; break; } default: { throw new HsqlDataSourceException( "CommandType not supported: " + m_commandType); // NOI18N } } m_statement = session.PrepareStatement(sql); // no longer valid m_commandTextBatch = null; } }
/// <summary> /// Handles a savepoint request. /// </summary> /// <param name="type"> /// The request type. /// </param> /// <param name="savePointName"> /// The name of the save point. /// </param> internal void HandleSavepointRequest(SavepointRequestType type, string savePointName) { CheckValid(); CheckSavepointName(savePointName); HsqlSession session = m_connection.Session; switch (type) { case SavepointRequestType.Savepoint: { session.ExecuteDirect(string.Concat("SAVEPOINT ", savePointName)); break; } case SavepointRequestType.ReleaseSavepoint: { session.ExecuteDirect(string.Concat( "RELEASE SAVEPOINT ", savePointName)); break; } case SavepointRequestType.RollbackToSavepoint: { session.ExecuteDirect(string.Concat( "ROLLBACK TO SAVEPOINT ", savePointName)); break; } default: { // paranoia mode: never happens in practice. throw new HsqlDataSourceException(string.Concat( "Unhandled SavepointRequestType: ", type), org.hsqldb.Trace.GENERAL_ERROR, "S1000"); } } }
/// <summary> /// Closes this connection. /// </summary> internal void CloseInternal() { ConnectionState state = m_connectionState; if (state == ConnectionState.Closed) { return; } HsqlSession session = m_session; if (m_session == null) { // Sanity-Check: Should never happen. throw new InvalidOperationException( "HsqlSession is null"); // NOI18N } // Handle dispose/close while enlisted in a system transaction. HsqlTransaction transaction = m_transaction; HsqlEnlistment enlistment = m_enlistment; bool enlisted = (enlistment != null); bool preserveEnlistment = (enlisted && !enlistment.m_disposeConnection); if (preserveEnlistment) { #if DEBUG // Without this, it is difficult to debug // because the m_enlistment's connection // ceases to be this one and this connection // loses its reference to the enlistment // (m_enlistment is set null below). m_enlistment_dbg = m_enlistment; #endif // ...then until it ceases to participate in a // System.Transactions.Transaction, the enlistment // needs a valid local transaction to commit or // rollback HsqlConnection connection = new HsqlConnection(this); connection.m_connectionState = ConnectionState.Open; connection.m_session = session; connection.m_enlistment = enlistment; connection.m_transaction = transaction; enlistment.m_dbConnection = connection; enlistment.m_disposeConnection = true; if (transaction != null) { transaction.m_connection = connection; } } SetStateInternal(ConnectionState.Closed); m_session = null; m_transaction = null; m_enlistment = null; m_dbMetaData = null; m_settings = null; if (!enlisted) { // No need to roll back here. This will happen automatically // a moment later on the back end in response to the // session.Close() call below. if (transaction != null) { transaction.DisposeInternal(/*rollback*/ false); } // release the back-end session and any associated resources, // such as network sockets, etc. session.Close(); } }
/// <summary> /// Provides the core logic for the /// <see cref="ExecuteReader(CommandBehavior)"/> method. /// </summary> /// <param name="behavior">The requested behavior.</param> /// <returns> /// The result generated by executing the query. /// </returns> internal HsqlDataReader ExecuteReaderInternal(CommandBehavior behavior) { if (Behavior.IsSchemaOnly(behavior)) { bool wasAlreadyPrepared = IsPrepared; if (!wasAlreadyPrepared) { Prepare(); // already correctly locked. } Result descriptor = m_statement.ResultDescriptor; HsqlCommand originatingCommand = this; HsqlConnection originatingConnection = m_dbConnection; HsqlDataReader reader0 = new HsqlDataReader(descriptor, behavior, originatingCommand, originatingConnection); if (Behavior.IsKeyInfo(behavior)) { // Do it now, so that it does not fail later if // originating connection is closed before first // client invocation of reader.GetSchemaTable(). reader0.GetSchemaTable(); } if (!wasAlreadyPrepared) { UnPrepare(); } return(reader0); } Result result; int maxRows = (Behavior.IsSingleRow(behavior)) ? 1 : 0; if (IsPrepared) { ApplyParameters(); HsqlSession session = Session; session.MaxRows = maxRows; result = m_statement.Execute(session); } else { HsqlSession session = Session; session.MaxRows = maxRows; result = session.ExecuteDirect(StaticallyBoundCommandText); } HsqlDataReader reader = new HsqlDataReader(result, behavior, this, this.m_dbConnection); if (Behavior.IsKeyInfo(behavior)) { // Do it now, so that it does not fail later if // originating connection is closed before first // client invocation of reader.GetSchemaTable(). reader.GetSchemaTable(); } return(reader); }