Search in sources :

Example 1 with HeapRowLocation

use of org.apache.derby.impl.store.access.heap.HeapRowLocation 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)

Aggregations

ArrayList (java.util.ArrayList)1 UUID (org.apache.derby.catalog.UUID)1 PreparedStatement (org.apache.derby.iapi.sql.PreparedStatement)1 ResultSet (org.apache.derby.iapi.sql.ResultSet)1 ExecRow (org.apache.derby.iapi.sql.execute.ExecRow)1 NumberDataValue (org.apache.derby.iapi.types.NumberDataValue)1 CheckInfo (org.apache.derby.impl.sql.execute.DeferredConstraintsMemory.CheckInfo)1 HeapRowLocation (org.apache.derby.impl.store.access.heap.HeapRowLocation)1