Search in sources :

Example 11 with ResultSet

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

the class ConstraintConstantAction method validateConstraint.

/**
 * Evaluate a check constraint or not null column constraint.
 * Generate a query of the
 * form SELECT COUNT(*) FROM t where NOT(<check constraint>)
 * and run it by compiling and executing it.   Will
 * work ok if the table is empty and query returns null.
 *
 * @param constraintName	constraint name
 * @param constraintText	constraint text
 * @param constraintId      constraint id
 * @param td				referenced table
 * @param lcc				the language connection context
 * @param isCheckConstraint	the constraint is a check constraint
 * @param isInitiallyDeferred {@code true} if the constraint is
 *                          initially deferred
 *
 * @return true if null constraint passes, false otherwise
 *
 * @exception StandardException if check constraint fails
 */
static boolean validateConstraint(String constraintName, String constraintText, UUID constraintId, TableDescriptor td, LanguageConnectionContext lcc, boolean isCheckConstraint, boolean isInitiallyDeferred) throws StandardException {
    StringBuilder checkStmt = new StringBuilder();
    /* should not use select sum(not(<check-predicate>) ? 1: 0) because
		 * that would generate much more complicated code and may exceed Java
		 * limits if we have a large number of check constraints, beetle 4347
		 */
    checkStmt.append("SELECT COUNT(*) FROM ");
    checkStmt.append(td.getQualifiedName());
    checkStmt.append(" WHERE NOT(");
    checkStmt.append(constraintText);
    checkStmt.append(")");
    ResultSet rs = null;
    try {
        PreparedStatement ps = lcc.prepareInternalStatement(checkStmt.toString());
        // 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.
        rs = ps.executeSubStatement(lcc, false, 0L);
        ExecRow row = rs.getNextRow();
        if (SanityManager.DEBUG) {
            if (row == null) {
                SanityManager.THROWASSERT("did not get any rows back from query: " + checkStmt.toString());
            }
        }
        Number value = ((Number) ((NumberDataValue) row.getRowArray()[0]).getObject());
        /*
			** Value may be null if there are no rows in the
			** table.
			*/
        if ((value != null) && (value.longValue() != 0)) {
            // check constraint is violated.
            if (isCheckConstraint) {
                if (isInitiallyDeferred) {
                    // Remember the violation
                    List<UUID> violatingConstraints = new ArrayList<UUID>();
                    violatingConstraints.add(constraintId);
                    // FIXME: We don't know the row locations of the
                    // violating rows, so for now, just pretend we know one,
                    // then invalidate the row location information forcing
                    // full table check at validation time
                    CheckInfo[] newCi = new CheckInfo[1];
                    DeferredConstraintsMemory.rememberCheckViolations(lcc, td.getObjectID(), td.getSchemaName(), td.getName(), null, violatingConstraints, new HeapRowLocation(), /* dummy */
                    newCi);
                    newCi[0].setInvalidatedRowLocations();
                } else {
                    throw StandardException.newException(SQLState.LANG_ADD_CHECK_CONSTRAINT_FAILED, constraintName, td.getQualifiedName(), value.toString());
                }
            }
            /*
				 * for not null constraint violations exception will be thrown in caller
				 * check constraint will not get here since exception is thrown
				 * above
				 */
            return false;
        }
    } finally {
        if (rs != null) {
            rs.close();
        }
    }
    return true;
}
Also used : HeapRowLocation(org.apache.derby.impl.store.access.heap.HeapRowLocation) ResultSet(org.apache.derby.iapi.sql.ResultSet) ExecRow(org.apache.derby.iapi.sql.execute.ExecRow) ArrayList(java.util.ArrayList) CheckInfo(org.apache.derby.impl.sql.execute.DeferredConstraintsMemory.CheckInfo) PreparedStatement(org.apache.derby.iapi.sql.PreparedStatement) UUID(org.apache.derby.catalog.UUID) NumberDataValue(org.apache.derby.iapi.types.NumberDataValue)

Example 12 with ResultSet

use of org.apache.derby.iapi.sql.ResultSet 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 13 with ResultSet

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

the class EmbedStatement method executeStatement.

// ///////////////////////////////////////////////////////////////////////
// 
// Implementation specific methods
// 
// ///////////////////////////////////////////////////////////////////////
/**
 *		Execute the current statement.
 *	    @exception SQLException thrown on failure.
 */
boolean executeStatement(Activation a, boolean executeQuery, boolean executeUpdate) throws SQLException {
    synchronized (getConnectionSynchronization()) {
        if (SanityManager.DEBUG) {
            // Ensure that clearResultSets has been called
            // to fulfill [JDBC4: section 15.2.5 ]
            // A ResultSet object is implicitly closed when:
            // The associated Statement object is re-executed
            SanityManager.ASSERT(results == null);
            SanityManager.ASSERT(dynamicResults == null);
            SanityManager.ASSERT(autoGeneratedKeysResultSet == null);
        }
        // make sure there's context
        setupContextStack();
        boolean retval;
        pvs = a.getParameterValueSet();
        try {
            clearWarnings();
            if (!forMetaData) {
                // commit the last statement if needed
                commitIfNeeded();
                needCommit();
            } else {
                if (lcc.getActivationCount() > 1) {
                // we do not want to commit here as there seems to be other
                // statements/resultSets currently opened for this connection.
                } else {
                    // we can legitimately commit
                    commitIfNeeded();
                    needCommit();
                }
            }
            // Get the statement. We don't care if it's invalid, because it
            // will be recompiled when we execute it if needed (DERBY-3024).
            PreparedStatement ps = a.getPreparedStatement();
            if (cursorName != null) {
                a.setCursorName(cursorName);
            }
            boolean executeHoldable = getExecuteHoldable();
            a.setResultSetHoldability(executeHoldable);
            // reset the activation to clear warnings
            // and clear existing result sets in case this has been cached
            a.reset();
            a.setMaxRows(maxRows);
            ResultSet resultsToWrap = ps.execute(a, forMetaData, timeoutMillis);
            addWarning(ps.getCompileTimeWarnings());
            addWarning(a.getWarnings());
            if (resultsToWrap.returnsRows()) {
                // executeUpdate() is not allowed.
                if (executeUpdate) {
                    throw StandardException.newException(SQLState.LANG_INVALID_CALL_TO_EXECUTE_UPDATE);
                }
                EmbedResultSet lresults = factory.newEmbedResultSet(getEmbedConnection(), resultsToWrap, forMetaData, this, ps.isAtomic());
                results = lresults;
                // outside of finalization.
                if (a.isSingleExecution())
                    lresults.singleUseActivation = a;
                updateCount = -1L;
                retval = true;
            } else {
                // the auto-generated keys resultset will be null if used for other statement
                if (a.getAutoGeneratedKeysResultsetMode() && (resultsToWrap.getAutoGeneratedKeysResultset() != null)) {
                    resultsToWrap.getAutoGeneratedKeysResultset().open();
                    autoGeneratedKeysResultSet = factory.newEmbedResultSet(getEmbedConnection(), resultsToWrap.getAutoGeneratedKeysResultset(), false, this, ps.isAtomic());
                }
                updateCount = resultsToWrap.modifiedRowCount();
                // note that we have none.
                results = null;
                int dynamicResultCount = 0;
                if (a.getDynamicResults() != null) {
                    dynamicResultCount = processDynamicResults(a.getDynamicResults(), a.getMaxDynamicResults());
                }
                // Don't need the result set any more
                resultsToWrap.close();
                // doesn't return exactly one ResultSet.
                if (executeQuery && dynamicResultCount != 1) {
                    throw StandardException.newException(SQLState.LANG_INVALID_CALL_TO_EXECUTE_QUERY);
                }
                // returns ResultSets.
                if (executeUpdate && dynamicResultCount > 0) {
                    throw StandardException.newException(SQLState.LANG_INVALID_CALL_TO_EXECUTE_UPDATE);
                }
                if (dynamicResultCount == 0) {
                    if (a.isSingleExecution()) {
                        a.close();
                    }
                    if (!forMetaData)
                        commitIfNeeded();
                    else {
                        if (lcc.getActivationCount() > 1) {
                        // we do not want to commit here as there seems to be other
                        // statements/resultSets currently opened for this connection.
                        } else {
                            // we can legitimately commit
                            commitIfNeeded();
                        }
                    }
                }
                retval = (dynamicResultCount > 0);
            }
            InterruptStatus.restoreIntrFlagIfSeen(lcc);
        } catch (Throwable t) {
            if (a.isSingleExecution()) {
                try {
                    a.close();
                } catch (Throwable tt) {
                    ;
                }
            }
            throw handleException(t);
        } finally {
            restoreContextStack();
        }
        return retval;
    }
}
Also used : ResultSet(org.apache.derby.iapi.sql.ResultSet) PreparedStatement(org.apache.derby.iapi.sql.PreparedStatement)

Aggregations

ResultSet (org.apache.derby.iapi.sql.ResultSet)13 Activation (org.apache.derby.iapi.sql.Activation)7 CursorActivation (org.apache.derby.iapi.sql.execute.CursorActivation)6 PreparedStatement (org.apache.derby.iapi.sql.PreparedStatement)4 StatementContext (org.apache.derby.iapi.sql.conn.StatementContext)3 Field (java.lang.reflect.Field)2 SQLWarning (java.sql.SQLWarning)2 ArrayList (java.util.ArrayList)2 LanguageConnectionContext (org.apache.derby.iapi.sql.conn.LanguageConnectionContext)2 ExecPreparedStatement (org.apache.derby.iapi.sql.execute.ExecPreparedStatement)2 ExecRow (org.apache.derby.iapi.sql.execute.ExecRow)2 NoPutResultSet (org.apache.derby.iapi.sql.execute.NoPutResultSet)2 DataValueDescriptor (org.apache.derby.iapi.types.DataValueDescriptor)2 UUID (org.apache.derby.catalog.UUID)1 ResultDescription (org.apache.derby.iapi.sql.ResultDescription)1 DependencyManager (org.apache.derby.iapi.sql.depend.DependencyManager)1 CursorResultSet (org.apache.derby.iapi.sql.execute.CursorResultSet)1 ExecCursorTableReference (org.apache.derby.iapi.sql.execute.ExecCursorTableReference)1 NumberDataValue (org.apache.derby.iapi.types.NumberDataValue)1 SQLBoolean (org.apache.derby.iapi.types.SQLBoolean)1