/// <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")));
            }
        }
Esempio n. 6
0
        /// <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();
            }
        }
Esempio n. 9
0
        /// <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);
        }