You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by da...@apache.org on 2014/03/11 15:46:17 UTC
svn commit: r1576367 [2/4] - in /db/derby/code/trunk/java:
engine/org/apache/derby/iapi/error/ engine/org/apache/derby/iapi/sql/compile/
engine/org/apache/derby/iapi/sql/conn/
engine/org/apache/derby/iapi/sql/dictionary/
engine/org/apache/derby/iapi/sq...
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj Tue Mar 11 14:46:15 2014
@@ -10422,60 +10422,97 @@ tableColumnList() throws StandardExcepti
}
/*
- * This method is called when a comment starting with --derby-properties is found.
- * Such a comment is a special directive to Derby and allows a sql to pass optimizer
- * overrides. Derby looks for propertyName=value [,propertyName=value]* after
- * --derby-properties and returns these properties in a Properties object as a return
- * value of this method.
- * The param propertiesUseAllowed true indicates that users are allowed to
- * specify optimizer overrides in the given context.
- * False means optimizer overrides in the given context are allowed internally
- * only eg impl/load/import.java specifies property insertMode=replace/bulkInsert
- * in the insert statement. This same property will not be acceptable from an
- * insert statement from a user sql.
+ * This method is called when a comment starting with "--derby-properties" is
+ * found. Such a comment is a special directive to Derby and allows an SQL
+ * statement to pass optimizer overrides. Derby looks for
+ *
+ * propertyName = value* [, propertyName = value]*
+ *
+ * after "--derby-properties" and returns these properties in a Properties
+ * object as a return value of this method. If the parameter
+ * "propertiesUseAllowed" is true, it indicates that users are allowed to
+ * specify optimizer overrides in the given context. False means optimizer
+ * overrides in the given context are allowed internally only, e.g. by the
+ * class org.apache.derby.impl.load.Import specifies the property
+ * "insertMode=replace/bulkInsert" in the INSERT statement. This same property
+ * will not be acceptable from an INSERT statement from a user SQL statement.
*/
Properties
propertyList(boolean propertiesUseAllowed) throws StandardException :
{
Properties properties = new FormatableProperties();
StringTokenizer commaSeparatedProperties;
- StringTokenizer equalOperatorSeparatedProperty;
+
}
{
- <DERBYDASHPROPERTIES> {
- //first use StringTokenizer to get tokens which are delimited by ,s
- commaSeparatedProperties = new StringTokenizer(getToken(1).image,",");
- while (commaSeparatedProperties.hasMoreTokens()) {
- //Now verify that tokens delimited by ,s follow propertyName=value pattern
- String currentProperty = commaSeparatedProperties.nextToken();
- equalOperatorSeparatedProperty = new StringTokenizer(currentProperty,"=", true);
- if (equalOperatorSeparatedProperty.countTokens() != 3)
- throw StandardException.newException(SQLState.PROPERTY_SYNTAX_INVALID);
- else {
- String key = equalOperatorSeparatedProperty.nextToken().trim();
- if (!equalOperatorSeparatedProperty.nextToken().equals("="))
- throw StandardException.newException(SQLState.PROPERTY_SYNTAX_INVALID);
- String value = equalOperatorSeparatedProperty.nextToken().trim();
- verifyImageLength(value);
- /* Trim off the leading and trailing ', and compress all '' to ' */
- if (value.startsWith("'") && value.endsWith("'"))
- value = StringUtil.compressQuotes(value.substring(1, value.length() - 1), SINGLEQUOTES);
- /* Trim off the leading and trailing ", and compress all "" to " */
- else if (value.startsWith("\"") && value.endsWith("\""))
- value = StringUtil.compressQuotes(value.substring(1, value.length() - 1), DOUBLEQUOTES);
- else
- value = value.toUpperCase();
- // Do not allow user to specify multiple values for the same key
- if (properties.put(key, value) != null)
- {
- throw StandardException.newException(SQLState.LANG_DUPLICATE_PROPERTY, key);
- }
- }
- }
- //if this property override is supported in internal mode only, then do that verification here.
- if (!propertiesUseAllowed)
- checkInternalFeature("DERBY-PROPERTIES");
- return properties;
+ <DERBYDASHPROPERTIES> {
+ // First use StringTokenizer to get tokens which are delimited by
+ // commas
+ commaSeparatedProperties = new StringTokenizer(getToken(1).image, ",");
+
+ while (commaSeparatedProperties.hasMoreTokens()) {
+
+ // Now verify that tokens delimited by commas follow
+ // "propertyName=value" pattern
+ String currentProperty = commaSeparatedProperties.nextToken();
+
+ // Use a new tokenizer to parse "propertyName=value". Let it
+ // return the '=' delimiter as well.
+ StringTokenizer equalOperatorSeparatedProperty =
+ new StringTokenizer(currentProperty, "=", true);
+
+ if (equalOperatorSeparatedProperty.countTokens() != 3) {
+ // should see exactly three tokens: propertyName, '=' and
+ // value.
+ throw StandardException.newException(
+ SQLState.PROPERTY_SYNTAX_INVALID);
+ } else {
+ // ignore blanks around key
+ String key = equalOperatorSeparatedProperty.nextToken().trim();
+
+ if (!equalOperatorSeparatedProperty.nextToken().equals("=")) {
+ throw StandardException.newException(
+ SQLState.PROPERTY_SYNTAX_INVALID);
+ }
+
+ // Also ignore blanks around value, canonize to upper case
+ // unless we have surrounding quotes.
+ String value =
+ equalOperatorSeparatedProperty.nextToken().trim();
+
+ verifyImageLength(value);
+
+ if (value.startsWith("'") && value.endsWith("'")) {
+ // Trim off the leading and trailing ', and compress all
+ // '' to '
+ value = StringUtil.compressQuotes(
+ value.substring(1, value.length() - 1), SINGLEQUOTES);
+ } else if (value.startsWith("\"") && value.endsWith("\"")) {
+ // Trim off the leading and trailing ", and compress all
+ // "" to "
+ value = StringUtil.compressQuotes(
+ value.substring(1, value.length() - 1), DOUBLEQUOTES);
+
+ } else {
+ value = value.toUpperCase();
+ }
+
+ // Do not allow user to specify multiple values for the same
+ // key.
+ if (properties.put(key, value) != null) {
+ throw StandardException.newException(
+ SQLState.LANG_DUPLICATE_PROPERTY, key);
+ }
+ }
+ }
+
+ // If this property override is supported in internal mode only, then
+ // do that verification here.
+ if (!propertiesUseAllowed) {
+ checkInternalFeature("DERBY-PROPERTIES");
+ }
+
+ return properties;
}
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java Tue Mar 11 14:46:15 2014
@@ -21,7 +21,6 @@
package org.apache.derby.impl.sql.conn;
-import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
@@ -78,7 +77,6 @@ import org.apache.derby.iapi.sql.execute
import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
import org.apache.derby.iapi.sql.execute.ExecutionStmtValidator;
import org.apache.derby.iapi.sql.execute.RunTimeStatistics;
-import org.apache.derby.iapi.store.access.BackingStoreHashtable;
import org.apache.derby.iapi.store.access.TransactionController;
import org.apache.derby.iapi.store.access.XATransactionController;
import org.apache.derby.iapi.transaction.TransactionControl;
@@ -89,9 +87,11 @@ import org.apache.derby.impl.sql.Generic
import org.apache.derby.impl.sql.GenericStatement;
import org.apache.derby.impl.sql.compile.CompilerContextImpl;
import org.apache.derby.impl.sql.execute.AutoincrementCounter;
-import org.apache.derby.impl.sql.execute.DeferredDuplicates;
+import org.apache.derby.impl.sql.execute.DeferredConstraintsMemory;
+import org.apache.derby.impl.sql.execute.DeferredConstraintsMemory.CheckInfo;
+import org.apache.derby.impl.sql.execute.DeferredConstraintsMemory.UniquePkInfo;
+import org.apache.derby.impl.sql.execute.DeferredConstraintsMemory.ValidationInfo;
import org.apache.derby.shared.common.sanity.SanityManager;
-
/**
* LanguageConnectionContext keeps the pool of prepared statements,
* activations, and cursors in use by the current connection.
@@ -316,7 +316,7 @@ public class GenericLanguageConnectionCo
* saved for deferred constraints in this transaction, keyed by the
* conglomerate id. Checked at commit time, then discarded.
*/
- private HashMap<Long, BackingStoreHashtable> deferredHashTables;
+ private HashMap<Long, ValidationInfo> deferredHashTables;
/*
constructor
@@ -3751,7 +3751,8 @@ public class GenericLanguageConnectionCo
final SQLSessionContext ssc = getCurrentSQLSessionContext(a);
sc.setDeferredAll(ssc.getDeferredAll());
- sc.setConstraintModes(ssc.getConstraintModes());
+ sc.setConstraintModes(ssc.getUniquePKConstraintModes());
+ sc.setCheckConstraintModes(ssc.getCheckConstraintModes());
StatementContext stmctx = getStatementContext();
@@ -3796,24 +3797,67 @@ public class GenericLanguageConnectionCo
// Check all constraints that were deferred inside the routine
// but whose constraint mode is immediate on the outside. If
// any of these violate the constraints, roll back.
- Set<Map.Entry<Long, BackingStoreHashtable>> es =
- deferredHashTables.entrySet();
+ Set<Map.Entry<Long, ValidationInfo>> es = deferredHashTables.entrySet();
- for (Map.Entry<Long, BackingStoreHashtable> e : es) {
- final long indexCID = e.getKey().longValue();
+ for (Map.Entry<Long, ValidationInfo> e : es) {
- boolean effectivelyDeferred = effectivelyDeferred(caller, indexCID);
+ if (e.getValue() instanceof UniquePkInfo) {
- if (effectivelyDeferred ) {
- // the constraint is also deferred in the calling context
- continue;
- }
- // The constraint must have been deferred inside the routine
- if (SanityManager.DEBUG) {
- SanityManager.ASSERT(effectivelyDeferred(nested, indexCID));
- }
+ final long indexCID = e.getKey().longValue();
+
+ boolean effectivelyDeferred =
+ effectivelyDeferred(caller, indexCID);
+
+ if (effectivelyDeferred ) {
+ // the constraint is also deferred in the calling context
+ continue;
+ }
- doValidateConstraint(e.getKey().longValue(), e.getValue(), true);
+ doValidateUniquePKConstraint(
+ e.getKey().longValue(),
+ (UniquePkInfo)e.getValue(),
+ true);
+
+ } else if (e.getValue() instanceof CheckInfo) {
+
+ final long baseTableCID = e.getKey().longValue();
+ CheckInfo ci = (CheckInfo)e.getValue();
+
+ // check if any of the constraints involved is immediate on
+ // the outside
+ boolean allEffectivelyDeferred = true;
+
+ for (UUID uid : ci.getCulprints()) {
+ if (!effectivelyDeferred(caller, uid) &&
+ effectivelyDeferred(nested, uid)) {
+
+ // at least one check constraint changed back
+ // from being deferred to immediate, so check
+ // all immediates
+
+ // FIXME: could be optimized if we knew
+ // exactly which constraints failed under the
+ // deferred regime: that might save us from
+ // checking in a few cases.
+ allEffectivelyDeferred = false;
+ break;
+ }
+ }
+
+ if (allEffectivelyDeferred) {
+ continue;
+ }
+
+ doValidateUniqueCheckConstraints(
+ baseTableCID,
+ null,
+ (CheckInfo)e.getValue(),
+ true);
+ } else {
+ if (SanityManager.DEBUG) {
+ SanityManager.NOTREACHED();
+ }
+ }
}
}
@@ -3840,6 +3884,26 @@ public class GenericLanguageConnectionCo
return effectivelyDeferred;
}
+ private boolean effectivelyDeferred(SQLSessionContext sc, UUID constraintId)
+ throws StandardException {
+
+ final Boolean deferred = sc.isDeferred(constraintId);
+ final boolean effectivelyDeferred;
+ final DataDictionary dd = getDataDictionary();
+
+ if (deferred != null) {
+ effectivelyDeferred = deferred.booleanValue();
+ } else {
+ // no explicit setting applicable, use initial constraint mode
+ final ConstraintDescriptor conDesc =
+ dd.getConstraintDescriptor(constraintId);
+ effectivelyDeferred = conDesc.initiallyDeferred();
+ }
+
+ return effectivelyDeferred;
+ }
+
+
/**
* @see LanguageConnectionContext#setupSubStatementSessionContext(Activation a)
*/
@@ -3944,33 +4008,76 @@ public class GenericLanguageConnectionCo
}
/**
- * {@inheritDoc}
- */
- public void setDeferred(Activation a, long conglomId, boolean deferred)
- throws StandardException {
+ * For check constraints
+ *
+ * @param a activation
+ * @param basetableCID the conglomerate id of the base table on which
+ * the constraint is defined
+ * @param constraintId the constraint id
+ * @param deferred the constraint mode
+ * @throws StandardException standard error policy
+ */
+ public void setConstraintDeferred(
+ final Activation a,
+ final long basetableCID,
+ final UUID constraintId,
+ final boolean deferred) throws StandardException {
+
if (!deferred) {
- // Moving to immediate, check whats done in this transaction first
- validateDeferredConstraint(conglomId);
+ // Moving to immediate, check what's done in this transaction first
+ validateDeferredConstraint(basetableCID, constraintId);
}
- getCurrentSQLSessionContext(a).setDeferred(conglomId, deferred);
+
+ getCurrentSQLSessionContext(a).setDeferred(constraintId, deferred);
}
- public boolean isEffectivelyDeferred(Activation a, long conglomId)
- throws StandardException {
+ /**
+ * For unique and primary key constraints
+ *
+ * @param a activation
+ * @param indexCID the conglomerate id of the supporting index
+ * @param deferred constraint mode
+ * @throws StandardException standard error policy
+ */
+ public void setConstraintDeferred(
+ final Activation a,
+ final long indexCID,
+ final boolean deferred) throws StandardException {
+
+ if (!deferred) {
+ // Moving to immediate, check what's done in this transaction first
+ validateDeferredConstraint(indexCID, null);
+ }
+
+ getCurrentSQLSessionContext(a).setDeferred(indexCID, deferred);
+
+ }
+
+ public boolean isEffectivelyDeferred(
+ final Activation a,
+ long conglomId) throws StandardException {
+
return effectivelyDeferred(getCurrentSQLSessionContext(a), conglomId);
}
+ public boolean isEffectivelyDeferred(
+ final Activation a,
+ final UUID constraintId) throws StandardException {
+
+ return effectivelyDeferred(getCurrentSQLSessionContext(a),
+ constraintId);
+ }
public void checkIntegrity() throws StandardException {
validateDeferredConstraints(true);
clearDeferreds();
}
- public void invalidateDeferredConstraintsData(long indexCID)
+ public void forgetDeferredConstraintsData(final long conglomId)
throws StandardException {
if (deferredHashTables != null &&
- deferredHashTables.containsKey(Long.valueOf(indexCID))) {
- deferredHashTables.remove(Long.valueOf(indexCID));
+ deferredHashTables.containsKey(Long.valueOf(conglomId))) {
+ deferredHashTables.remove(Long.valueOf(conglomId));
}
}
@@ -3985,7 +4092,7 @@ public class GenericLanguageConnectionCo
/**
* {@inheritDoc}
*/
- public void setDeferredAll(Activation a, boolean deferred)
+ public void setDeferredAll(final Activation a, final boolean deferred)
throws StandardException {
if (!deferred) {
validateDeferredConstraints(false);
@@ -4000,49 +4107,86 @@ public class GenericLanguageConnectionCo
/**
* {@inheritDoc}
*/
- public HashMap<Long, BackingStoreHashtable> getDeferredHashTables() {
+ public HashMap<Long, ValidationInfo> getDeferredHashTables() {
if (deferredHashTables == null) {
- deferredHashTables = new HashMap<Long, BackingStoreHashtable>();
+ deferredHashTables = new HashMap<Long, ValidationInfo>();
}
return deferredHashTables;
}
- private void validateDeferredConstraints(boolean rollbackOnError)
+ private void validateDeferredConstraints(final boolean rollbackOnError)
throws StandardException {
+
if (deferredHashTables == null) {
// Nothing to do
return;
}
- Set<Map.Entry<Long, BackingStoreHashtable>> es =
+ final Set<Map.Entry<Long, ValidationInfo>> es =
deferredHashTables.entrySet();
- for (Map.Entry<Long, BackingStoreHashtable> e : es) {
- doValidateConstraint(e.getKey().longValue(),
- e.getValue(),
- rollbackOnError);
+ for (Map.Entry<Long, ValidationInfo> e : es) {
+ if (e.getValue() instanceof UniquePkInfo) {
+ doValidateUniquePKConstraint(e.getKey().longValue(),
+ (UniquePkInfo)e.getValue(),
+ rollbackOnError);
+ } else if (e.getValue() instanceof CheckInfo) {
+ doValidateUniqueCheckConstraints(e.getKey().longValue(),
+ null,
+ (CheckInfo)e.getValue(),
+ rollbackOnError);
+ } else {
+ if (SanityManager.DEBUG) {
+ SanityManager.NOTREACHED();
+ }
+ }
}
}
- private void validateDeferredConstraint(long indexCID)
- throws StandardException {
- BackingStoreHashtable ht = null;
+ private void validateDeferredConstraint(
+ final long conglomCID,
+ final UUID constraintId) throws StandardException {
+
+ ValidationInfo vi = null;
if (deferredHashTables == null ||
- (ht = deferredHashTables.get(indexCID)) == null) {
+ (vi = deferredHashTables.get(conglomCID)) == null) {
// Nothing to do
return;
}
- doValidateConstraint(indexCID, ht, false);
- deferredHashTables.remove(indexCID);
+
+ if (vi instanceof CheckInfo) {
+ doValidateUniqueCheckConstraints(
+ conglomCID, constraintId, (CheckInfo)vi, false);
+ } else if (vi instanceof UniquePkInfo) {
+ doValidateUniquePKConstraint(conglomCID, (UniquePkInfo)vi, false);
+ } else {
+ if (SanityManager.DEBUG) {
+ SanityManager.NOTREACHED();
+ }
+ }
+
+ deferredHashTables.remove(conglomCID);
}
- private void doValidateConstraint(
- long indexCID,
- BackingStoreHashtable ht,
- boolean rollbackOnError) throws StandardException {
+ private void doValidateUniquePKConstraint(
+ final long indexCID,
+ final UniquePkInfo ui,
+ final boolean rollbackOnError) throws StandardException {
- DeferredDuplicates.validate(tran, indexCID, this, ht, rollbackOnError);
+ DeferredConstraintsMemory.validateUniquePK(
+ this, indexCID, ui.infoRows, rollbackOnError);
}
+
+ private void doValidateUniqueCheckConstraints(
+ final long baseTableCID,
+ final UUID constraintId,
+ final CheckInfo ci,
+ final boolean rollbackOnError) throws StandardException {
+
+ DeferredConstraintsMemory.validateCheck(
+ this, baseTableCID, constraintId, ci, rollbackOnError);
+ }
+
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/SQLSessionContextImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/SQLSessionContextImpl.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/SQLSessionContextImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/SQLSessionContextImpl.java Tue Mar 11 14:46:15 2014
@@ -22,6 +22,7 @@
package org.apache.derby.impl.sql.conn;
import java.util.HashMap;
+import org.apache.derby.catalog.UUID;
import org.apache.derby.iapi.sql.conn.SQLSessionContext;
import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
@@ -32,13 +33,23 @@ public class SQLSessionContextImpl imple
private SchemaDescriptor currentDefaultSchema;
/**
- * Maps a conglomerate id (key) into a Boolean for deferrable constraints.
+ * Maps a conglomerate id (key) into a Boolean for deferrable primary/unique
+ * constraints.
* There is a 1-1 correspondence for these backing indexes, they are not
* shared). If the Boolean value is {@code FALSE}, we have immediate
* checking, if it is {@code TRUE} we have deferred checking. Cf. SQL
* SET CONSTRAINT.
*/
- private HashMap<Long, Boolean> constraintModes;
+ private HashMap<Long, Boolean> uniquePKConstraintModes;
+
+ /**
+ * Maps a constraint id (key) into a Boolean for deferrable check
+ * constraints.
+ * If the Boolean value is {@code FALSE}, we have immediate
+ * checking, if it is {@code TRUE} we have deferred checking. Cf. SQL
+ * SET CONSTRAINT.
+ */
+ private HashMap<UUID, Boolean> checkConstraintModes;
/**
* True if all deferrable constraints are deferred in this transaction.
@@ -51,10 +62,6 @@ public class SQLSessionContextImpl imple
currentRole = null;
currentDefaultSchema = sd;
this.currentUser = currentUser;
-
- if (constraintModes != null) {
- this.constraintModes = new HashMap<Long,Boolean>(constraintModes);
- }
}
public void setRole(String role) {
@@ -84,9 +91,15 @@ public class SQLSessionContextImpl imple
/**
* {@inheritDoc}
*/
- public HashMap<Long, Boolean> getConstraintModes() {
- return constraintModes != null ?
- new HashMap<Long, Boolean>(constraintModes) :
+ public HashMap<Long, Boolean> getUniquePKConstraintModes() {
+ return uniquePKConstraintModes != null ?
+ new HashMap<Long, Boolean>(uniquePKConstraintModes) :
+ null;
+ }
+
+ public HashMap<UUID, Boolean> getCheckConstraintModes() {
+ return checkConstraintModes != null ?
+ new HashMap<UUID, Boolean>(checkConstraintModes) :
null;
}
@@ -94,30 +107,59 @@ public class SQLSessionContextImpl imple
* {@inheritDoc}
*/
public void setConstraintModes(HashMap<Long, Boolean> hm) {
- this.constraintModes = hm != null ?
+ this.uniquePKConstraintModes = hm != null ?
new HashMap<Long, Boolean>(hm) : null;
}
+ public void setCheckConstraintModes(HashMap<UUID, Boolean> hm) {
+ this.checkConstraintModes = hm != null ?
+ new HashMap<UUID, Boolean>(hm) : null;
+ }
+
/**
* {@inheritDoc}
*/
public void setDeferred(long conglomId, boolean deferred) {
- if (constraintModes == null) {
- constraintModes = new HashMap<Long, Boolean>();
+ if (uniquePKConstraintModes == null) {
+ uniquePKConstraintModes = new HashMap<Long, Boolean>();
}
- constraintModes.put(Long.valueOf(conglomId),
+ uniquePKConstraintModes.put(Long.valueOf(conglomId),
Boolean.valueOf(deferred));
}
+ public void setDeferred(UUID constraintId, boolean deferred) {
+ if (checkConstraintModes == null) {
+ checkConstraintModes = new HashMap<UUID, Boolean>();
+ }
+
+ checkConstraintModes.put(constraintId, Boolean.valueOf(deferred));
+ }
+
/**
* {@inheritDoc}
*/
public Boolean isDeferred(long conglomId) {
Boolean v = null;
- if (constraintModes != null) {
- v = constraintModes.get(Long.valueOf(conglomId));
+ if (uniquePKConstraintModes != null) {
+ v = uniquePKConstraintModes.get(Long.valueOf(conglomId));
+ }
+
+ if (v != null) {
+ return v; // Trumps ALL setting since it must have been
+ // set later otherwise it would have been
+ // deleted
+ } else {
+ return deferredAll;
+ }
+ }
+
+ public Boolean isDeferred(UUID constraintId) {
+ Boolean v = null;
+
+ if (checkConstraintModes != null) {
+ v = checkConstraintModes.get(constraintId);
}
if (v != null) {
@@ -129,12 +171,17 @@ public class SQLSessionContextImpl imple
}
}
+
/**
* {@inheritDoc}
*/
public void resetConstraintModes() {
- if (constraintModes != null) {
- constraintModes.clear();
+ if (uniquePKConstraintModes != null) {
+ uniquePKConstraintModes.clear();
+ }
+
+ if (checkConstraintModes != null) {
+ checkConstraintModes.clear();
}
deferredAll = null;
@@ -147,8 +194,12 @@ public class SQLSessionContextImpl imple
deferredAll = deferred;
// This now overrides any individual constraint setting, so
// clear those.
- if (constraintModes != null) {
- constraintModes.clear();
+ if (uniquePKConstraintModes != null) {
+ uniquePKConstraintModes.clear();
+ }
+
+ if (checkConstraintModes != null) {
+ checkConstraintModes.clear();
}
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterConstraintConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterConstraintConstantAction.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterConstraintConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterConstraintConstantAction.java Tue Mar 11 14:46:15 2014
@@ -160,7 +160,6 @@ public class AlterConstraintConstantActi
"DEFERRED CONSTRAINTS");
if (constraintType == DataDictionary.FOREIGNKEY_CONSTRAINT ||
- constraintType == DataDictionary.CHECK_CONSTRAINT ||
constraintType == DataDictionary.NOTNULL_CONSTRAINT ||
!characteristics[2] /* not enforced */) {
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java Tue Mar 11 14:46:15 2014
@@ -22,6 +22,7 @@
package org.apache.derby.impl.sql.execute;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Properties;
@@ -314,6 +315,27 @@ class AlterTableConstantAction extends D
int numRows = 0;
boolean tableScanned = false;
+ if (compressTable || truncateTable) {
+ final HashMap<Long, DeferredConstraintsMemory.ValidationInfo> vis =
+ lcc.getDeferredHashTables();
+ td = dd.getTableDescriptor(tableId);
+ final DeferredConstraintsMemory.ValidationInfo vi =
+ vis.get(td.getHeapConglomerateId());
+
+ if (td == null) {
+ throw StandardException.newException(
+ SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tableName);
+ }
+
+ if (vi != null &&
+ vi instanceof DeferredConstraintsMemory.CheckInfo) {
+ // We can not use row locations when re-visiting offending
+ // rows in this table, since we are truncating or compressing.
+ ((DeferredConstraintsMemory.CheckInfo)vi).
+ setInvalidatedRowLocations();
+ }
+ }
+
//Following if is for inplace compress. Compress using temporary
//tables to do the compression is done later in this method.
if (compressTable)
@@ -420,6 +442,7 @@ class AlterTableConstantAction extends D
else
dm.invalidateFor(td, DependencyManager.ALTER_TABLE, lcc);
+
// Are we working on columns?
if (columnInfo != null)
{
@@ -546,10 +569,18 @@ class AlterTableConstantAction extends D
conIndex++)
{
ConstraintConstantAction cca = constraintActions[conIndex];
+ boolean isCheckInitiallyDeferred = false;
if (cca instanceof CreateConstraintConstantAction)
{
- int constraintType = cca.getConstraintType();
+ final CreateConstraintConstantAction ccca =
+ (CreateConstraintConstantAction)cca;
+
+ int constraintType = ccca.getConstraintType();
+
+ isCheckInitiallyDeferred =
+ (constraintType == DataDictionary.CHECK_CONSTRAINT) &&
+ ccca.isInitiallyDeferred();
/* Some constraint types require special checking:
* Check - table must be empty, for now
@@ -586,6 +617,14 @@ class AlterTableConstantAction extends D
tableScanned = true;
numRows = getSemiRowCount(tc);
}
+
+ if (isCheckInitiallyDeferred) {
+ // Need to do this early to get UUID
+ // assigned
+ constraintActions[conIndex].
+ executeConstantAction(activation);
+ }
+
if (numRows > 0)
{
/*
@@ -594,11 +633,15 @@ class AlterTableConstantAction extends D
** is ok to do the check now rather than try
** to lump together several checks.
*/
+
ConstraintConstantAction.validateConstraint(
cca.getConstraintName(),
((CreateConstraintConstantAction)cca).getConstraintText(),
+ cca.getConstraintId(),
td,
- lcc, true);
+ lcc,
+ true,
+ isCheckInitiallyDeferred);
}
break;
}
@@ -619,7 +662,10 @@ class AlterTableConstantAction extends D
}
}
- constraintActions[conIndex].executeConstantAction(activation);
+ if (!isCheckInitiallyDeferred) {
+ constraintActions[conIndex].
+ executeConstantAction(activation);
+ } // else it is done early, see above.
}
}
@@ -3144,7 +3190,12 @@ class AlterTableConstantAction extends D
return (numIndexes > 0);
}
- /**
+ public boolean needsRowLocationForDeferredCheckConstraints()
+ {
+ return false;
+ }
+
+ /**
* @see RowLocationRetRowSource#rowLocation
* @exception StandardException on error
*/
@@ -3518,11 +3569,13 @@ class AlterTableConstantAction extends D
if (foundNullable && numRows > 0)
{
if (!ConstraintConstantAction.validateConstraint(
- (String) null,
- constraintText.toString(),
- td,
- lcc,
- false))
+ (String) null,
+ constraintText.toString(),
+ null, /* not used for not nullable constraints yet */
+ td,
+ lcc,
+ false,
+ false /* not used for not nullable constraints yet */))
{
if (errorMsg.equals(SQLState.LANG_NULL_DATA_IN_PRIMARY_KEY_OR_UNIQUE_CONSTRAINT))
{ //alter table add primary key
@@ -3623,4 +3676,11 @@ class AlterTableConstantAction extends D
return null;
}
+ public void offendingRowLocation(
+ RowLocation rl, long containdId) throws StandardException {
+ if (SanityManager.DEBUG) {
+ SanityManager.NOTREACHED();
+ }
+ }
+
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CardinalityCounter.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CardinalityCounter.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CardinalityCounter.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CardinalityCounter.java Tue Mar 11 14:46:15 2014
@@ -26,6 +26,7 @@ import org.apache.derby.iapi.error.Stand
import org.apache.derby.iapi.store.access.RowLocationRetRowSource;
import org.apache.derby.iapi.types.DataValueDescriptor;
import org.apache.derby.iapi.types.RowLocation;
+import org.apache.derby.shared.common.sanity.SanityManager;
/**
* This is a decorator (in Design Patterns Terminology)
@@ -53,6 +54,18 @@ class CardinalityCounter implements RowL
return rowSource.needsRowLocation();
}
+
+ public boolean needsRowLocationForDeferredCheckConstraints()
+ {
+ return rowSource.needsRowLocationForDeferredCheckConstraints();
+ }
+
+ public void offendingRowLocation(
+ RowLocation rl, long containdId) throws StandardException {
+ rowSource.offendingRowLocation(rl, containdId);
+ }
+
+
/** @see RowLocationRetRowSource#rowLocation */
public void rowLocation(RowLocation rl) throws StandardException
{
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ConstraintConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ConstraintConstantAction.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ConstraintConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ConstraintConstantAction.java Tue Mar 11 14:46:15 2014
@@ -21,11 +21,13 @@
package org.apache.derby.impl.sql.execute;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
import org.apache.derby.catalog.UUID;
import org.apache.derby.iapi.error.StandardException;
import org.apache.derby.iapi.reference.SQLState;
import org.apache.derby.iapi.services.io.FormatableBitSet;
-import org.apache.derby.shared.common.sanity.SanityManager;
import org.apache.derby.iapi.sql.PreparedStatement;
import org.apache.derby.iapi.sql.ResultSet;
import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
@@ -34,12 +36,17 @@ import org.apache.derby.iapi.sql.diction
import org.apache.derby.iapi.sql.dictionary.ReferencedKeyConstraintDescriptor;
import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
import org.apache.derby.iapi.sql.execute.ExecRow;
+import org.apache.derby.iapi.store.access.BackingStoreHashtable;
import org.apache.derby.iapi.store.access.ConglomerateController;
import org.apache.derby.iapi.store.access.GroupFetchScanController;
import org.apache.derby.iapi.store.access.ScanController;
import org.apache.derby.iapi.store.access.TransactionController;
import org.apache.derby.iapi.types.DataValueDescriptor;
import org.apache.derby.iapi.types.NumberDataValue;
+import org.apache.derby.impl.sql.execute.DeferredConstraintsMemory.CheckInfo;
+import org.apache.derby.impl.sql.execute.DeferredConstraintsMemory.ValidationInfo;
+import org.apache.derby.impl.store.access.heap.HeapRowLocation;
+import org.apache.derby.shared.common.sanity.SanityManager;
/**
* This class describes actions that are ALWAYS performed for a
* constraint creation at Execution time.
@@ -56,6 +63,7 @@ public abstract class ConstraintConstant
protected String schemaName;
protected UUID schemaId;
protected IndexConstantAction indexAction;
+ protected UUID constraintId;
// CONSTRUCTORS
/**
@@ -110,6 +118,15 @@ public abstract class ConstraintConstant
*/
public String getConstraintName() { return constraintName; }
+ /**
+ * Get the constraint id of the constraint
+ * @return constraint id
+ */
+ public UUID getConstraintId() {
+ return constraintId;
+ }
+
+
/**
* Get the associated index constant action.
*
@@ -252,9 +269,12 @@ public abstract class ConstraintConstant
*
* @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
*
@@ -264,9 +284,11 @@ public abstract class ConstraintConstant
(
String constraintName,
String constraintText,
+ UUID constraintId,
TableDescriptor td,
LanguageConnectionContext lcc,
- boolean isCheckConstraint
+ boolean isCheckConstraint,
+ boolean isInitiallyDeferred
)
throws StandardException
{
@@ -306,10 +328,40 @@ public abstract class ConstraintConstant
*/
if ((value != null) && (value.longValue() != 0))
{
- //check constraint violated
- if (isCheckConstraint)
- throw StandardException.newException(SQLState.LANG_ADD_CHECK_CONSTRAINT_FAILED,
- constraintName, td.getQualifiedName(), value.toString());
+ // The query yielded a valid value > 0, so we must conclude the
+ // 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
+ DeferredConstraintsMemory.rememberCheckViolations(
+ lcc,
+ td.getHeapConglomerateId(),
+ td.getSchemaName(),
+ td.getName(),
+ null,
+ violatingConstraints,
+ new HeapRowLocation() /* dummy */);
+ HashMap<Long, ValidationInfo>
+ hashTables = lcc.getDeferredHashTables();
+ CheckInfo ci = (CheckInfo)hashTables.get(
+ Long.valueOf(td.getHeapConglomerateId()));
+ ci.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
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateConstraintConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateConstraintConstantAction.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateConstraintConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateConstraintConstantAction.java Tue Mar 11 14:46:15 2014
@@ -282,7 +282,7 @@ public class CreateConstraintConstantAct
indexId = conglomDesc.getUUID();
}
- UUID constraintId = uuidFactory.createUUID();
+ UUID constrId= uuidFactory.createUUID();
boolean[] defaults = new boolean[]{
ConstraintDefinitionNode.DEFERRABLE_DEFAULT,
@@ -296,7 +296,6 @@ public class CreateConstraintConstantAct
"DEFERRED CONSTRAINTS");
if (constraintType == DataDictionary.FOREIGNKEY_CONSTRAINT ||
- constraintType == DataDictionary.CHECK_CONSTRAINT ||
constraintType == DataDictionary.NOTNULL_CONSTRAINT ||
!characteristics[2] /* not enforced */) {
@@ -322,7 +321,7 @@ public class CreateConstraintConstantAct
characteristics[0], //deferable,
characteristics[1], //initiallyDeferred,
genColumnPositions(td, false), //int[],
- constraintId,
+ constrId,
indexId,
sd,
characteristics[2],
@@ -337,7 +336,7 @@ public class CreateConstraintConstantAct
characteristics[0], //deferable,
characteristics[1], //initiallyDeferred,
genColumnPositions(td, false), //int[],
- constraintId,
+ constrId,
indexId,
sd,
characteristics[2],
@@ -351,7 +350,7 @@ public class CreateConstraintConstantAct
td, constraintName,
characteristics[0], //deferable,
characteristics[1], //initiallyDeferred,
- constraintId,
+ constrId,
constraintText,
new ReferencedColumnsDescriptorImpl(genColumnPositions(td, false)), //int[],
sd,
@@ -372,7 +371,7 @@ public class CreateConstraintConstantAct
characteristics[0], //deferable,
characteristics[1], //initiallyDeferred,
genColumnPositions(td, false), //int[],
- constraintId,
+ constrId,
indexId,
sd,
referencedConstraint,
@@ -470,6 +469,8 @@ public class CreateConstraintConstantAct
getTableDescriptor(),
DependencyManager.CREATE_CONSTRAINT, lcc);
}
+
+ this.constraintId = constrId;
}
/**
@@ -482,6 +483,11 @@ public class CreateConstraintConstantAct
return (constraintType == DataDictionary.FOREIGNKEY_CONSTRAINT);
}
+
+ boolean isInitiallyDeferred() {
+ return characteristics[1];
+ }
+
/**
* Generate an array of column positions for the column list in
* the constraint.
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateIndexConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateIndexConstantAction.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateIndexConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateIndexConstantAction.java Tue Mar 11 14:46:15 2014
@@ -826,18 +826,17 @@ class CreateIndexConstantAction extends
numColumnOrderings = unique ? baseColumnPositions.length :
baseColumnPositions.length + 1;
- sortObserver =
- new UniqueIndexSortObserver(
- tc,
- lcc,
- DeferredDuplicates.UNDEFINED_CONGLOMERATE,
- true,
- uniqueDeferrable,
- initiallyDeferred,
- indexOrConstraintName,
- indexTemplateRow,
- true,
- td.getName());
+ sortObserver = new UniqueIndexSortObserver(
+ tc,
+ lcc,
+ DeferredConstraintsMemory.UNDEFINED_CONGLOMERATE,
+ true,
+ uniqueDeferrable,
+ initiallyDeferred,
+ indexOrConstraintName,
+ indexTemplateRow,
+ true,
+ td.getName());
}
else
{
@@ -854,16 +853,16 @@ class CreateIndexConstantAction extends
//use sort operator which treats nulls unequal
sortObserver =
new UniqueWithDuplicateNullsIndexSortObserver(
- tc,
- lcc,
- DeferredDuplicates.UNDEFINED_CONGLOMERATE,
- true,
- hasDeferrableChecking,
- initiallyDeferred,
- indexOrConstraintName,
- indexTemplateRow,
- true,
- td.getName());
+ tc,
+ lcc,
+ DeferredConstraintsMemory.UNDEFINED_CONGLOMERATE,
+ true,
+ hasDeferrableChecking,
+ initiallyDeferred,
+ indexOrConstraintName,
+ indexTemplateRow,
+ true,
+ td.getName());
}
}
else
@@ -915,7 +914,7 @@ class CreateIndexConstantAction extends
(long[]) null);
if (initiallyDeferred) {
- DeferredDuplicates.associateDuplicatesWithConglomerate(
+ DeferredConstraintsMemory.associateDuplicatesWithConglomerate(
lcc, conglomId);
}
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DMLWriteResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DMLWriteResultSet.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DMLWriteResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DMLWriteResultSet.java Tue Mar 11 14:46:15 2014
@@ -22,10 +22,10 @@
package org.apache.derby.impl.sql.execute;
import java.io.InputStream;
+import org.apache.derby.catalog.UUID;
import org.apache.derby.iapi.error.StandardException;
import org.apache.derby.iapi.services.io.FormatableBitSet;
import org.apache.derby.iapi.services.io.StreamStorable;
-import org.apache.derby.shared.common.sanity.SanityManager;
import org.apache.derby.iapi.sql.Activation;
import org.apache.derby.iapi.sql.ResultColumnDescriptor;
import org.apache.derby.iapi.sql.ResultDescription;
@@ -38,11 +38,12 @@ import org.apache.derby.iapi.store.acces
import org.apache.derby.iapi.transaction.TransactionControl;
import org.apache.derby.iapi.types.DataTypeDescriptor;
import org.apache.derby.iapi.types.DataValueDescriptor;
+import org.apache.derby.shared.common.sanity.SanityManager;
/**
* For INSERT/UPDATE/DELETE impls. Used to tag them.
*/
-abstract class DMLWriteResultSet extends NoRowsResultSetImpl
+abstract public class DMLWriteResultSet extends NoRowsResultSetImpl
{
protected WriteCursorConstantAction constantAction;
protected int[] baseRowReadMap;
@@ -353,5 +354,12 @@ abstract class DMLWriteResultSet extends
return row;
}
-
+
+ public void rememberConstraint(UUID cid) throws StandardException {
+ if (SanityManager.DEBUG) {
+ // This method should be overriden by InsertResultSet and
+ // UpdateResultSet, other shouldn't need it.
+ SanityManager.NOTREACHED();
+ }
+ }
}
Added: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DeferredConstraintsMemory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DeferredConstraintsMemory.java?rev=1576367&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DeferredConstraintsMemory.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DeferredConstraintsMemory.java Tue Mar 11 14:46:15 2014
@@ -0,0 +1,588 @@
+/*
+
+ Derby - Class org.apache.derby.impl.sql.execute.DeferredConstraintsMemory
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ */
+
+package org.apache.derby.impl.sql.execute;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.derby.catalog.UUID;
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.services.io.FormatableBitSet;
+import org.apache.derby.iapi.sql.PreparedStatement;
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
+import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;
+import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
+import org.apache.derby.iapi.sql.execute.ExecRow;
+import org.apache.derby.iapi.store.access.BackingStoreHashtable;
+import org.apache.derby.iapi.store.access.ScanController;
+import org.apache.derby.iapi.store.access.TransactionController;
+import org.apache.derby.iapi.types.DataValueDescriptor;
+import org.apache.derby.iapi.types.RowLocation;
+import org.apache.derby.iapi.types.SQLRef;
+import org.apache.derby.shared.common.reference.SQLState;
+import org.apache.derby.shared.common.sanity.SanityManager;
+
+/**
+ * This class provides support for deferrable constraints. When the constraint
+ * mode is deferred, any violation of the constraint should not be flagged
+ * until the constraint mode is switched back to immediate, which may happen by
+ * explicitly setting the constraint mode to immediate, or implicitly at commit
+ * time. It may also happen implicitly when returning from a stored procedure
+ * if the constraint mode is immediate in the caller context.
+ * <p>
+ * The approach taken in Derby to support deferred constraints is to make a note
+ * when the violation happens (at insert or update time), and then remember that
+ * violation until the mode switches back as described above. We note exactly
+ * which rows cause violations, so checking can happen as quickly as possible
+ * when we get there. The core mechanism used to remember the violations as well
+ * as the deferred checking is embodied in this class.
+ *
+ */
+final public class DeferredConstraintsMemory
+{
+ /**
+ * For unique and primary key constraints, sometimes we need to save
+ * duplicate rows before we know the id of the constraint index, so we
+ * assign the duplicates row a temporary constraint id
+ * (UNDEFINED_CONGLOMERATE) and fix it up later.
+ * @see #associateDuplicatesWithConglomerate
+ */
+ public final static long UNDEFINED_CONGLOMERATE = -1;
+
+ /**
+ * Save the contents of an constraint supporting index row in a
+ * hash table (which may spill to disk) for later checking,
+ * typically on transaction commit, or upon request.
+ *
+ * @param lcc the language connection context
+ * @param deferredRowsHashTable
+ * client cached value
+ * @param indexCID the identity of the index conglomerate which supports
+ * the deferred constraint
+ * @param insertRow the duplicate row to be saved in the hash table
+ * for later checking
+ * @return the hash table (for caching by client to minimize lookups)
+ * @throws StandardException standard error policy
+ */
+ public static BackingStoreHashtable rememberDuplicate(
+ final LanguageConnectionContext lcc,
+ BackingStoreHashtable deferredRowsHashTable,
+ final long indexCID,
+ final DataValueDescriptor[] insertRow) throws StandardException {
+
+ // Don't copy the RowLocation, we don't need it:
+ final int keyLength = insertRow.length -1 ;
+
+ if (deferredRowsHashTable == null) {
+ // Use the backing hashtable for this index's deferred rows
+ // by checking the transaction's map of such backing hash
+ // tables (one per index conglomerate). Use it if it
+ // exists, else make a new one.
+
+ final HashMap<Long, ValidationInfo> hashTables =
+ lcc.getDeferredHashTables();
+ final ValidationInfo vi = hashTables.get(Long.valueOf(indexCID));
+
+ if (vi == null) {
+ deferredRowsHashTable =
+ makeDeferredHashTable(lcc.getTransactionExecute(), keyLength);
+
+ hashTables.put(
+ Long.valueOf(indexCID),
+ new UniquePkInfo(deferredRowsHashTable));
+ } else {
+ deferredRowsHashTable = vi.infoRows;
+ }
+ }
+
+ DataValueDescriptor[] hashRowArray = new DataValueDescriptor[keyLength];
+ System.arraycopy(insertRow, 0, hashRowArray, 0, keyLength);
+ deferredRowsHashTable.putRow(true, hashRowArray, null);
+
+ return deferredRowsHashTable;
+ }
+
+ /**
+ * Save the row location of an offending row (one or more check constraints
+ * were violated) in a hash table (which may spill to disk) for later
+ * checking, typically on transaction commit, or upon request.
+ *
+ * The row locations are subject to invalidation, cf.
+ * {@code CheckInfo#setInvalidatedRowLocations}.
+ *
+ * @param basetableCID the identity of the base table conglomerate for
+ * which we have seen a violated deferred check constraint
+ * @param schemaName the schema of the target table
+ * @param tableName the target table name
+ * @param deferredCheckViolations
+ * client cached value
+ * @param lcc the language connection context
+ * @param violatingCheckConstraints offending constraint(s)
+ * @param offendingRow the duplicate row to be saved in the hash table
+ * for later checking
+ * @return the hash table (for caching by client to minimize lookups)
+ * @throws StandardException standard error policy
+ */
+ public static BackingStoreHashtable rememberCheckViolations(
+ final LanguageConnectionContext lcc,
+ final long basetableCID,
+ final String schemaName,
+ final String tableName,
+ BackingStoreHashtable deferredCheckViolations,
+ final List<UUID> violatingCheckConstraints,
+ final RowLocation offendingRow) throws StandardException {
+
+ if (violatingCheckConstraints.isEmpty()) {
+ return null;
+ }
+
+ if (deferredCheckViolations == null) {
+ // Use the backing hashtable for this base tables deferred rows
+ // by checking the transaction's map of such backing hash
+ // tables (one per base table conglomerate). Use it if it
+ // exists, else make a new one.
+
+ final HashMap<Long, ValidationInfo> hashTables =
+ lcc.getDeferredHashTables();
+ final CheckInfo vi =
+ (CheckInfo)hashTables.get(Long.valueOf(basetableCID));
+
+ if (vi == null) {
+ // size 1 below: the row location in the target table of the
+ // offending row
+ deferredCheckViolations =
+ makeDeferredHashTable(lcc.getTransactionExecute(), 1);
+
+ hashTables.put(Long.valueOf(basetableCID),
+ new CheckInfo(deferredCheckViolations,
+ schemaName,
+ tableName,
+ violatingCheckConstraints));
+ } else {
+ vi.addCulprits(violatingCheckConstraints);
+ deferredCheckViolations = vi.infoRows;
+ }
+ }
+
+ final DataValueDescriptor[] hashRowArray = new DataValueDescriptor[1];
+ hashRowArray[0] = new SQLRef(offendingRow).cloneValue(true);
+ deferredCheckViolations.putRow(true, hashRowArray, null);
+
+ return deferredCheckViolations;
+ }
+
+
+ /**
+ * After having belatedly learned the identity of the conglomerate, we now
+ * associate the conglomerate id information with the saved duplicates
+ * memory. Used for unique and primary key constraints.
+ * See {@link #UNDEFINED_CONGLOMERATE}.
+ *
+ * @param lcc language connection context
+ * @param indexCID the id of the index conglomerate supporting the
+ * deferred constraint
+ */
+ public static void associateDuplicatesWithConglomerate(
+ final LanguageConnectionContext lcc,
+ final long indexCID) {
+
+ final HashMap<Long, ValidationInfo> hashTables =
+ lcc.getDeferredHashTables();
+
+ if (hashTables == null) {
+ return; // no duplicates recorded in this transaction
+ }
+
+ final ValidationInfo ht = hashTables.remove(
+ Long.valueOf(UNDEFINED_CONGLOMERATE));
+
+ if (ht != null) {
+ hashTables.put(indexCID, ht);
+ } // else no duplicates recorded for this index
+ }
+
+ /**
+ * The conglomerate id for an index with deferred row checking needs
+ * updating in the memory if the underlying index is rebuilt, for example
+ * on bulk insert for import.
+ *
+ * @param lcc the language connection context needed to find the
+ * deferred rows information if any
+ * @param oldIndexCID the old id of the supporting index
+ * @param newIndexCID the new id of the supporting index after recreation
+ */
+ public static void updateIndexCID(
+ final LanguageConnectionContext lcc,
+ final long oldIndexCID,
+ final long newIndexCID) {
+
+ final HashMap<Long, ValidationInfo> hashTables =
+ lcc.getDeferredHashTables();
+
+ if (hashTables == null) {
+ return; // no duplicates recorded in this transaction
+ }
+
+ final ValidationInfo ht = hashTables.remove(
+ Long.valueOf(oldIndexCID));
+
+ if (ht != null) {
+ hashTables.put(Long.valueOf(newIndexCID), ht);
+ }
+ }
+
+ private static BackingStoreHashtable makeDeferredHashTable(
+ final TransactionController tc,
+ final int cols) throws StandardException {
+
+ // key: all columns (these are index rows, or a row containing a
+ // row location)
+ final int[] keyCols = new int[cols];
+
+ for (int i = 0; i < cols; i++) {
+ keyCols[i] = i;
+ }
+
+ return new BackingStoreHashtable(
+ tc,
+ null,
+ keyCols,
+ true, // remove duplicates: no need for more copies:
+ // one is enough to know what to look for on commit
+ -1,
+ HashScanResultSet.DEFAULT_MAX_CAPACITY,
+ HashScanResultSet.DEFAULT_INITIAL_CAPACITY,
+ HashScanResultSet.DEFAULT_MAX_CAPACITY,
+ false,
+ false);
+ }
+
+ private static BackingStoreHashtable makeDeferredCheck(
+ final TransactionController tc,
+ final int cols) throws StandardException {
+
+ // key: all columns (these are index rows)
+ final int[] keyCols = new int[cols];
+
+ for (int i = 0; i < cols; i++) {
+ keyCols[i] = i;
+ }
+
+ return new BackingStoreHashtable(
+ tc,
+ null,
+ keyCols,
+ true, // remove duplicates: no need for more copies:
+ // one is enough to know what to look for on commit
+ -1,
+ HashScanResultSet.DEFAULT_MAX_CAPACITY,
+ HashScanResultSet.DEFAULT_INITIAL_CAPACITY,
+ HashScanResultSet.DEFAULT_MAX_CAPACITY,
+ false,
+ false);
+ }
+
+ /**
+ * Validate one primary key or unique constraint
+ *
+ * @param lcc The language connection context
+ * @param indexCID The conglomerate id of the index backing the constraint
+ * @param ht Cached saved rows if any
+ * @param rollbackOnError {@code true} if we should roll back the
+ * transaction if we see a violation of the constraint
+ * @throws StandardException
+ */
+ public static void validateUniquePK(
+ final LanguageConnectionContext lcc,
+ final long indexCID,
+ final BackingStoreHashtable ht,
+ final boolean rollbackOnError) throws StandardException {
+
+ final TransactionController tc = lcc.getTransactionExecute();
+ final Enumeration<?> e = ht.elements();
+
+ while (e.hasMoreElements()) {
+ final DataValueDescriptor[] key =
+ (DataValueDescriptor[])e.nextElement();
+
+ // FIXME: This is not very efficient: we could sort the rows in the
+ // hash table, and then check all rows using a single scan.
+ ScanController indexSC = null;
+ boolean sawException = false;
+
+ try {
+ indexSC = tc.openScan(
+ indexCID,
+ false,
+ 0, // read only
+ TransactionController.MODE_RECORD,
+ TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK,
+ (FormatableBitSet)null, // retrieve all fields
+ key,
+ ScanController.GE, // startSearchOp
+ null,
+ key,
+ ScanController.GT);
+
+ if (indexSC.next()) {
+ if (indexSC.next()) {
+ // two matching rows found, constraint violated
+ final DataDictionary dd = lcc.getDataDictionary();
+ final ConglomerateDescriptor cd =
+ dd.getConglomerateDescriptor(indexCID);
+ final TableDescriptor td =
+ dd.getTableDescriptor(cd.getTableID());
+ final ConstraintDescriptor conDesc =
+ dd.getConstraintDescriptor(td, cd.getUUID());
+
+ throw StandardException.newException(
+ rollbackOnError ?
+ SQLState.LANG_DEFERRED_DUPLICATE_KEY_CONSTRAINT_T :
+ SQLState.LANG_DEFERRED_DUPLICATE_KEY_CONSTRAINT_S,
+ conDesc.getConstraintName(),
+ td.getName());
+ } // else exactly one row contains key: OK
+ } else {
+ // No rows contain key: OK, must have been deleted later
+ // in transaction, or we got here due to pessimistic
+ // assumption on a timeout while checking on the insert.
+ }
+ } catch (StandardException se) {
+ sawException = true;
+ throw se;
+ } finally {
+ // Clean up resource usage
+ try {
+ if (indexSC != null) {
+ indexSC.close();
+ }
+ } catch (StandardException ie) {
+ if (!sawException) {
+ throw ie;
+ } // else: can't let it shadow preceding exception
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Validate one or more CHECK constraints on a table.
+ * <p>
+ * Implementation note: We remember violations for a row by storing its row
+ * location in a disk based hash table, similar to what we do for the index
+ * location for primary key and unique constraints. As far as which
+ * constraints caused which violations, constraints are only presently
+ * remembered as having caused "one or more violations", i.e. for any
+ * violating row, we do not know at checking time exactly which constraint
+ * caused a problem for that exact row. So, for any given constraint which
+ * was violated in the transaction we visit all rows which had one or more
+ * violations and check again. This could be improved upon by remembering
+ * for each violating row the exact set of constraint(s) that saw a
+ * violation. Still, this is much faster than a full table scan in most use
+ * cases. We use a special internal query option to achieve this. The row
+ * locations may not be usable if Derby does a compress or otherwise makes
+ * them invalid. In that case we resort to a full table scan.
+ * @see ValidateCheckConstraintResultSet
+ *
+ * @param lcc The language connection context
+ * @param baseTableCID The conglomerate id of the base table for which
+ * we want to validate check constraints.
+ * @param constraintId If not {@code null}, check only for this
+ * constraint. This is used when switching mode to
+ * immediate. If {@code null}, we check all check
+ * constraints, i.e. at commit or if we have {@code
+ * SET CONSTRAINT ALL IMMEDIATE}.
+ * @param ci The constraints info for the table we need
+ * to perform the check on.
+ * @param rollbackOnError If {@code true} and a violation occurs, throw
+ * and exception that will cause rollback.
+ * @throws StandardException
+ * Default error policy
+ */
+ public static void validateCheck(
+ final LanguageConnectionContext lcc,
+ final long baseTableCID,
+ final UUID constraintId,
+ final CheckInfo ci,
+ final boolean rollbackOnError) throws StandardException {
+
+ final TransactionController tc = lcc.getTransactionExecute();
+ final DataDictionary dd = lcc.getDataDictionary();
+ final SchemaDescriptor sd = dd.getSchemaDescriptor(
+ ci.schemaName, tc, true);
+
+ if (sd == null) {
+ if (SanityManager.DEBUG) {
+ // dropping of a schema shouold drop any tables and their
+ // constraints, which in turn should drop any deferred
+ // constraint memory of them.
+ SanityManager.NOTREACHED();
+ } else {
+ return;
+ }
+ }
+
+ final TableDescriptor td = dd.getTableDescriptor(ci.tableName, sd, tc);
+
+ if (td == null) {
+ if (SanityManager.DEBUG) {
+ // dropping of a table shouold drop any
+ // constraints, which in turn should drop any deferred
+ // constraint memory of them. Renaming of a table with
+ // constrants is not presently allowed. FIXME: use UUID
+ // instead of string here, more stable reference.
+ SanityManager.NOTREACHED();
+ }
+ } else {
+ for (UUID id : ci.culprits) {
+ if (constraintId == null || constraintId.equals(id)) {
+ final ConstraintDescriptor cd =
+ dd.getConstraintDescriptor(id);
+ final StringBuilder checkStmt = new StringBuilder();
+ checkStmt.append("SELECT 1 FROM ");
+ checkStmt.append(td.getQualifiedName());
+
+ // If a compress has happened in this transaction, we can't
+ // trust the rowLocations, so make a full table scan. If
+ // not, we optimize by using a special result set type
+ // which utilized the saved away row locations for the
+ // offending rows, so we only visit those when checking.
+ // I.e. other rows are known to be good a priori.
+ if (!ci.isInvalidated()) {
+ checkStmt.append(
+ " --DERBY-PROPERTIES joinStrategy=nestedLoop, " +
+ " index=null, " +
+ " validateCheckConstraint=");
+ checkStmt.append(Long.toString(baseTableCID));
+ checkStmt.append('\n');
+ }
+
+ checkStmt.append(" WHERE NOT(");
+ checkStmt.append(cd.getConstraintText());
+ checkStmt.append(')');
+
+ BasicNoPutResultSetImpl rs = null;
+ final PreparedStatement ps = lcc.prepareInternalStatement(
+ lcc.getDefaultSchema(),
+ checkStmt.toString(),
+ true,
+ true);
+ try {
+ rs = (BasicNoPutResultSetImpl)ps.execute(
+ ps.getActivation(lcc, false), false, 0L);
+ final ExecRow row = rs.getNextRowCore();
+
+ if (row != null) {
+ //check constraint violated
+
+ throw StandardException.newException(
+ rollbackOnError ?
+ SQLState.LANG_DEFERRED_CHECK_CONSTRAINT_T :
+ SQLState.LANG_DEFERRED_CHECK_CONSTRAINT_S,
+ cd.getConstraintName(),
+ td.getName(),
+ cd.getConstraintText());
+ }
+ } finally {
+ if (rs != null) {
+ try {
+ rs.close();
+ } catch (StandardException e) {}
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Class hierarchy carrying the information we need to validate
+ * some deferred constraint. For unique and primary key constraints, we
+ * only need the index row. For check constraints we need the target table
+ * name, schema name and some other info also.
+ */
+ abstract public static class ValidationInfo {
+ public final BackingStoreHashtable infoRows;
+
+ public ValidationInfo(final BackingStoreHashtable infoRows) {
+ this.infoRows = infoRows;
+ }
+ }
+
+ /**
+ * Info needed for unique and primary key constraints
+ */
+ public static class UniquePkInfo extends ValidationInfo {
+ public UniquePkInfo(final BackingStoreHashtable infoRows) {
+ super(infoRows);
+ }
+ }
+
+ /**
+ * Info needed for check constraints
+ */
+ public static class CheckInfo extends ValidationInfo {
+ final private String schemaName;
+ final private String tableName;
+
+ private List<UUID> culprits; // constraints that were violated
+ // for this table so far
+ private boolean invalidatedDueToCompress;
+
+ public CheckInfo(
+ final BackingStoreHashtable infoRows,
+ final String schemaName,
+ final String tableName,
+ final List<UUID> culprits) {
+
+ super(infoRows);
+ this.schemaName = schemaName;
+ this.tableName = tableName;
+ this.culprits = new ArrayList<UUID>(culprits);
+ }
+
+ public void setInvalidatedRowLocations() {
+ invalidatedDueToCompress = true;
+ }
+
+ public boolean isInvalidated() {
+ return invalidatedDueToCompress;
+ }
+
+ public void addCulprits(List<UUID> newCulprits) {
+ final Set<UUID> old = new HashSet<UUID>(culprits);
+ old.addAll(newCulprits);
+ culprits = new ArrayList<UUID>(old);
+ }
+
+ public List<UUID> getCulprints() {
+ return culprits;
+ }
+ }
+}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericConstantActionFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericConstantActionFactory.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericConstantActionFactory.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericConstantActionFactory.java Tue Mar 11 14:46:15 2014
@@ -754,7 +754,7 @@ public class GenericConstantActionFactor
}
/**
- * Make the ConstantAction for a Replicated INSERT statement.
+ * Make the ConstantAction for a INSERT statement.
*
* @param conglomId Conglomerate ID.
* @param heapSCOCI StaticCompiledOpenConglomInfo for target heap.
@@ -766,7 +766,10 @@ public class GenericConstantActionFactor
* @param deferred True means deferred insert
* @param tableIsPublished true if table is published, false otherwise
* @param tableID table id
- * @param targetProperties Properties on the target table
+ * @param hasDeferrableChecks
+ * The target table has deferrable CHECK
+ * constraints
+ * @param targetProperties Properties on the target table
* @param fkInfo Array of structures containing foreign key info,
* if any (may be null)
* @param triggerInfo Array of structures containing trigger info,
@@ -792,7 +795,8 @@ public class GenericConstantActionFactor
StaticCompiledOpenConglomInfo[] indexSCOCIs,
String[] indexNames,
boolean deferred,
- boolean tableIsPublished,
+ boolean tableIsPublished,
+ boolean hasDeferrableChecks,
UUID tableID,
int lockMode,
Object insertToken,
@@ -819,6 +823,7 @@ public class GenericConstantActionFactor
indexSCOCIs,
indexNames,
deferred,
+ hasDeferrableChecks,
targetProperties,
tableID,
lockMode,
@@ -904,14 +909,14 @@ public class GenericConstantActionFactor
/**
- * Make the ConstantAction for a Replicated DELETE statement.
+ * Make the ConstantAction for an UPDATE statement.
*
- * @param conglomId Conglomerate ID.
- * @param tableType type of this table
+ * @param targetTableDesc Descriptor for the updated table
* @param heapSCOCI StaticCompiledOpenConglomInfo for heap.
* @param irgs Index descriptors
* @param indexCIDS Conglomerate IDs of indices
- * @param indexSCOCIs StaticCompiledOpenConglomInfos for indexes.
+ * @param indexSCOCIs StaticCompiledOpenConglomInfos for indexes.
+ * @param indexNames
* @param deferred True means deferred update
* @param targetUUID UUID of target table
* @param lockMode The lock mode to use
@@ -919,6 +924,7 @@ public class GenericConstantActionFactor
* @param tableIsPublished true if table is published, false otherwise
* @param changedColumnIds Array of ids of changes columns
* @param keyPositions positions of primary key columns in base row
+ * @param updateToken
* @param fkInfo Array of structures containing foreign key info,
* if any (may be null)
* @param triggerInfo Array of structures containing trigger info,
@@ -930,12 +936,12 @@ public class GenericConstantActionFactor
* @param positionedUpdate is this a positioned update
* @param singleRowSource Whether or not source is a single row source
* @param underMerge True if this is an action of a MERGE statement.
+ * @return The constant action constructed
*
* @exception StandardException Thrown on failure
*/
public UpdateConstantAction getUpdateConstantAction(
- long conglomId,
- int tableType,
+ TableDescriptor targetTableDesc,
StaticCompiledOpenConglomInfo heapSCOCI,
IndexRowGenerator[] irgs,
long[] indexCIDS,
@@ -950,7 +956,7 @@ public class GenericConstantActionFactor
Object updateToken,
FKInfo[] fkInfo,
TriggerInfo triggerInfo,
- FormatableBitSet baseRowReadList,
+ FormatableBitSet baseRowReadList,
int[] baseRowReadMap,
int[] streamStorableHeapColIds,
int numColumns,
@@ -961,7 +967,7 @@ public class GenericConstantActionFactor
throws StandardException
{
return new UpdateConstantAction(
- conglomId,
+ targetTableDesc,
heapSCOCI,
irgs,
indexCIDS,
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java Tue Mar 11 14:46:15 2014
@@ -66,14 +66,24 @@ public class GenericResultSetFactory imp
@see ResultSetFactory#getInsertResultSet
@exception StandardException thrown on error
*/
- public ResultSet getInsertResultSet(NoPutResultSet source, GeneratedMethod generationClauses,
- GeneratedMethod checkGM, int fullTemplate)
+ 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, activation);
+
+ return new InsertResultSet(source,
+ generationClauses,
+ checkGM,
+ fullTemplate,
+ schemaName,
+ tableName,
+ activation);
}
/**
@@ -226,6 +236,8 @@ public class GenericResultSetFactory imp
int cloneMapItem,
boolean reuseResult,
boolean doesProjection,
+ boolean validatingCheckConstraint,
+ long validatingBaseTableCID,
double optimizerEstimatedRowCount,
double optimizerEstimatedCost)
throws StandardException
@@ -235,6 +247,8 @@ public class GenericResultSetFactory imp
constantRestriction, mapRefItem, cloneMapItem,
reuseResult,
doesProjection,
+ validatingCheckConstraint,
+ validatingBaseTableCID,
optimizerEstimatedRowCount,
optimizerEstimatedCost);
}
@@ -666,7 +680,65 @@ public class GenericResultSetFactory imp
optimizerEstimatedCost);
}
- /**
+ public NoPutResultSet getValidateCheckConstraintResultSet(
+ Activation activation,
+ long conglomId,
+ int scociItem,
+ int resultRowTemplate,
+ int resultSetNumber,
+ GeneratedMethod startKeyGetter,
+ int startSearchOperator,
+ GeneratedMethod stopKeyGetter,
+ int stopSearchOperator,
+ boolean sameStartStopPosition,
+ Qualifier[][] qualifiers,
+ String tableName,
+ String userSuppliedOptimizerOverrides,
+ String indexName,
+ boolean isConstraint,
+ boolean forUpdate,
+ int colRefItem,
+ int indexColItem,
+ int lockMode,
+ boolean tableLocked,
+ int isolationLevel,
+ boolean oneRowScan,
+ double optimizerEstimatedRowCount,
+ double optimizerEstimatedCost)
+ throws StandardException
+ {
+ StaticCompiledOpenConglomInfo scoci =
+ (StaticCompiledOpenConglomInfo)(activation.getPreparedStatement().
+ getSavedObject(scociItem));
+ return new ValidateCheckConstraintResultSet(
+ conglomId,
+ scoci,
+ activation,
+ resultRowTemplate,
+ resultSetNumber,
+ startKeyGetter,
+ startSearchOperator,
+ stopKeyGetter,
+ stopSearchOperator,
+ sameStartStopPosition,
+ qualifiers,
+ tableName,
+ userSuppliedOptimizerOverrides,
+ indexName,
+ isConstraint,
+ forUpdate,
+ colRefItem,
+ indexColItem,
+ lockMode,
+ tableLocked,
+ isolationLevel,
+ 1, // rowsPerRead is 1 if not a bulkTableScan
+ oneRowScan,
+ optimizerEstimatedRowCount,
+ optimizerEstimatedCost);
+ }
+
+ /**
Table/Index scan where rows are read in bulk
@see ResultSetFactory#getBulkTableScanResultSet
@exception StandardException thrown on error