Search in sources :

Example 16 with Activation

use of org.apache.derby.iapi.sql.Activation in project derby by apache.

the class GenericTriggerExecutor method executeSPS.

/**
 * Execute the given stored prepared statement.  We
 * just grab the prepared statement from the spsd,
 * get a new activation holder and let er rip.
 *
 * @param sps the SPS to execute
 * @param isWhen {@code true} if the SPS is for the WHEN clause,
 *               {@code false} otherwise
 * @return {@code true} if the SPS is for a WHEN clause and it evaluated
 *         to {@code TRUE}, {@code false} otherwise
 * @exception StandardException on error
 */
private boolean executeSPS(SPSDescriptor sps, boolean isWhen) throws StandardException {
    boolean recompile = false;
    boolean whenClauseWasTrue = false;
    // The prepared statement and the activation may already be available
    // if the trigger has been fired before in the same statement. (Only
    // happens with row triggers that are triggered by a statement that
    // touched multiple rows.) The WHEN clause and the trigger action have
    // their own prepared statement and activation. Fetch the correct set.
    ExecPreparedStatement ps = isWhen ? whenPS : actionPS;
    Activation spsActivation = isWhen ? spsWhenActivation : spsActionActivation;
    while (true) {
        /*
			** Only grab the ps the 1st time through.  This
			** way a row trigger doesn't do any unnecessary
			** setup work.
			*/
        if (ps == null || recompile) {
            // The SPS activation will set its parent activation from
            // the statement context. Reset it to the original parent
            // activation first so that it doesn't use the activation of
            // the previously executed SPS as parent. DERBY-6348.
            lcc.getStatementContext().setActivation(activation);
            /*
				** We need to clone the prepared statement so we don't
				** wind up marking that ps that is tied to sps as finished
				** during the course of execution.
				*/
            ps = sps.getPreparedStatement();
            ps = ps.getClone();
            // it should be valid since we've just prepared for it
            ps.setValid();
            spsActivation = ps.getActivation(lcc, false);
            /*
				** Normally, we want getSource() for an sps invocation
				** to be EXEC STATEMENT xxx, but in this case, since
				** we are executing the SPS in our own fashion, we want
				** the text to be the trigger action.  So set it accordingly.
				*/
            ps.setSource(sps.getText());
            ps.setSPSAction();
            // trigger fires multiple times.
            if (isWhen) {
                whenPS = ps;
                spsWhenActivation = spsActivation;
            } else {
                actionPS = ps;
                spsActionActivation = spsActivation;
            }
        }
        // save the active statement context for exception handling purpose
        StatementContext active_sc = lcc.getStatementContext();
        /*
			** Execute the activation.  If we have an error, we
			** are going to go to some extra work to pop off
			** our statement context.  This is because we are
			** a nested statement (we have 2 activations), but
			** we aren't a nested connection, so we have to
			** pop off our statementcontext to get error handling	
			** to work correctly.  This is normally a no-no, but
			** we are an unusual case.
			*/
        try {
            // This is a substatement; for now, we do not set any timeout
            // for it. We might change this behaviour later, by linking
            // timeout to its parent statement's timeout settings.
            ResultSet rs = ps.executeSubStatement(activation, spsActivation, false, 0L);
            if (isWhen) {
                // This is a WHEN clause. Expect a single BOOLEAN value
                // to be returned.
                ExecRow row = rs.getNextRow();
                if (SanityManager.DEBUG && row.nColumns() != 1) {
                    SanityManager.THROWASSERT("Expected WHEN clause to have exactly " + "one column, found: " + row.nColumns());
                }
                DataValueDescriptor value = row.getColumn(1);
                if (SanityManager.DEBUG) {
                    SanityManager.ASSERT(value instanceof SQLBoolean);
                }
                whenClauseWasTrue = !value.isNull() && value.getBoolean();
                if (SanityManager.DEBUG) {
                    SanityManager.ASSERT(rs.getNextRow() == null, "WHEN clause returned more than one row");
                }
            } else if (rs.returnsRows()) {
                // The result set was opened in ps.execute()
                while (rs.getNextRow() != null) {
                }
            }
            rs.close();
        } catch (StandardException e) {
            /* 
				** When a trigger SPS action is executed and results in 
				** an exception, the system needs to clean up the active 
				** statement context(SC) and the trigger execution context
				** (TEC) in language connection context(LCC) properly (e.g.:  
				** "Maximum depth triggers exceeded" exception); otherwise, 
				** this will leave old TECs lingering and may result in 
				** subsequent statements within the same connection to throw 
				** the same exception again prematurely.  
				**    
				** A new statement context will be created for the SPS before
				** it is executed.  However, it is possible for some 
				** StandardException to be thrown before a new statement 
				** context is pushed down to the context stack; hence, the 
				** trigger executor needs to ensure that the current active SC 
				** is associated with the SPS, so that it is cleaning up the 
				** right statement context in LCC. 
                **
                ** It is also possible that the error has already been handled
                ** on a lower level, especially if the trigger re-enters the
                ** JDBC layer. In that case, the current SC will be null.
				**    
				** When the active SC is cleaned up, the TEC will be removed
				** from LCC and the SC object will be popped off from the LCC 
				** as part of cleanupOnError logic.  
				 */
            /* retrieve the current active SC */
            StatementContext sc = lcc.getStatementContext();
            /* make sure that the cleanup is on the new SC */
            if (sc != null && active_sc != sc) {
                sc.cleanupOnError(e);
            }
            /* Handle dynamic recompiles */
            if (e.getMessageId().equals(SQLState.LANG_STATEMENT_NEEDS_RECOMPILE)) {
                recompile = true;
                sps.revalidate(lcc);
                continue;
            }
            spsActivation.close();
            throw e;
        }
        /* Done with execution without any recompiles */
        return whenClauseWasTrue;
    }
}
Also used : StandardException(org.apache.derby.shared.common.error.StandardException) ExecPreparedStatement(org.apache.derby.iapi.sql.execute.ExecPreparedStatement) ResultSet(org.apache.derby.iapi.sql.ResultSet) CursorResultSet(org.apache.derby.iapi.sql.execute.CursorResultSet) ExecRow(org.apache.derby.iapi.sql.execute.ExecRow) Activation(org.apache.derby.iapi.sql.Activation) DataValueDescriptor(org.apache.derby.iapi.types.DataValueDescriptor) SQLBoolean(org.apache.derby.iapi.types.SQLBoolean) StatementContext(org.apache.derby.iapi.sql.conn.StatementContext)

Example 17 with Activation

use of org.apache.derby.iapi.sql.Activation in project derby by apache.

the class GenericResultSetFactory method getMergeResultSet.

/**
 *		@see ResultSetFactory#getMergeResultSet
 *		@exception StandardException thrown on error
 */
public ResultSet getMergeResultSet(NoPutResultSet drivingLeftJoin) throws StandardException {
    Activation activation = drivingLeftJoin.getActivation();
    getAuthorizer(activation).authorize(activation, Authorizer.SQL_WRITE_OP);
    return new MergeResultSet(drivingLeftJoin, activation);
}
Also used : Activation(org.apache.derby.iapi.sql.Activation)

Example 18 with Activation

use of org.apache.derby.iapi.sql.Activation in project derby by apache.

the class GenericResultSetFactory method getInsertVTIResultSet.

/**
 *		@see ResultSetFactory#getInsertVTIResultSet
 *		@exception StandardException thrown on error
 */
public ResultSet getInsertVTIResultSet(NoPutResultSet source, NoPutResultSet vtiRS) throws StandardException {
    Activation activation = source.getActivation();
    getAuthorizer(activation).authorize(activation, Authorizer.SQL_WRITE_OP);
    return new InsertVTIResultSet(source, vtiRS, activation);
}
Also used : Activation(org.apache.derby.iapi.sql.Activation)

Example 19 with Activation

use of org.apache.derby.iapi.sql.Activation in project derby by apache.

the class GenericResultSetFactory method getUpdateResultSet.

/**
 *		@see ResultSetFactory#getUpdateResultSet
 *		@exception StandardException thrown on error
 */
public ResultSet getUpdateResultSet(NoPutResultSet source, GeneratedMethod generationClauses, GeneratedMethod checkGM) throws StandardException {
    Activation activation = source.getActivation();
    // assertion code will catch it.
    if (SanityManager.DEBUG) {
        SanityManager.ASSERT(getAuthorizer(activation) != null, "Authorizer is null");
    }
    getAuthorizer(activation).authorize(activation, Authorizer.SQL_WRITE_OP);
    return new UpdateResultSet(source, generationClauses, checkGM, activation);
}
Also used : Activation(org.apache.derby.iapi.sql.Activation)

Example 20 with Activation

use of org.apache.derby.iapi.sql.Activation in project derby by apache.

the class GenericResultSetFactory method getInsertResultSet.

/**
 *		@see ResultSetFactory#getInsertResultSet
 *		@exception StandardException thrown on error
 */
public ResultSet getInsertResultSet(NoPutResultSet source, GeneratedMethod generationClauses, GeneratedMethod checkGM, int fullTemplate, String schemaName, String tableName) throws StandardException {
    Activation activation = source.getActivation();
    getAuthorizer(activation).authorize(activation, Authorizer.SQL_WRITE_OP);
    return new InsertResultSet(source, generationClauses, checkGM, fullTemplate, schemaName, tableName, activation);
}
Also used : Activation(org.apache.derby.iapi.sql.Activation)

Aggregations

Activation (org.apache.derby.iapi.sql.Activation)25 CursorActivation (org.apache.derby.iapi.sql.execute.CursorActivation)10 ResultSet (org.apache.derby.iapi.sql.ResultSet)8 StatementContext (org.apache.derby.iapi.sql.conn.StatementContext)5 LanguageConnectionContext (org.apache.derby.iapi.sql.conn.LanguageConnectionContext)3 StandardException (org.apache.derby.shared.common.error.StandardException)3 SQLWarning (java.sql.SQLWarning)2 ResultDescription (org.apache.derby.iapi.sql.ResultDescription)2 SQLSessionContext (org.apache.derby.iapi.sql.conn.SQLSessionContext)2 CursorResultSet (org.apache.derby.iapi.sql.execute.CursorResultSet)2 ExecCursorTableReference (org.apache.derby.iapi.sql.execute.ExecCursorTableReference)2 ExecPreparedStatement (org.apache.derby.iapi.sql.execute.ExecPreparedStatement)2 IOException (java.io.IOException)1 Field (java.lang.reflect.Field)1 Method (java.lang.reflect.Method)1 GeneratedClass (org.apache.derby.iapi.services.loader.GeneratedClass)1 GeneratedMethod (org.apache.derby.iapi.services.loader.GeneratedMethod)1 PreparedStatement (org.apache.derby.iapi.sql.PreparedStatement)1 DependencyManager (org.apache.derby.iapi.sql.depend.DependencyManager)1 IndexRowGenerator (org.apache.derby.iapi.sql.dictionary.IndexRowGenerator)1