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;
}
Aggregations