--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.compile.ConstraintDefinitionNode\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.sql.compile;\r
+\r
+import org.apache.derby.iapi.sql.StatementType;\r
+\r
+import org.apache.derby.iapi.types.TypeId;\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.sql.depend.ProviderList;\r
+\r
+import org.apache.derby.impl.sql.compile.ActivationClassBuilder;\r
+\r
+import org.apache.derby.iapi.services.monitor.Monitor;\r
+\r
+import org.apache.derby.iapi.util.JBitSet;\r
+import org.apache.derby.iapi.util.ReuseFactory;\r
+\r
+import org.apache.derby.catalog.UUID;\r
+import org.apache.derby.iapi.services.uuid.UUIDFactory;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import java.util.Properties;\r
+\r
+/**\r
+ * A ConstraintDefintionNode is a class for all nodes that can represent\r
+ * constraint definitions.\r
+ *\r
+ */\r
+\r
+public class ConstraintDefinitionNode extends TableElementNode\r
+{\r
+ \r
+ private TableName constraintName;\r
+ protected int constraintType;\r
+ protected Properties properties;\r
+ ProviderList apl;\r
+\r
+ UUIDFactory uuidFactory;\r
+\r
+ String backingIndexName;\r
+ UUID backingIndexUUID;\r
+ int[] checkColumnReferences;\r
+ ResultColumnList columnList;\r
+ String constraintText;\r
+ ValueNode checkCondition;\r
+ private int behavior;\r
+ private int verifyType = DataDictionary.DROP_CONSTRAINT; // By default do not check the constraint type\r
+\r
+ public void init(\r
+ Object constraintName,\r
+ Object constraintType,\r
+ Object rcl,\r
+ Object properties,\r
+ Object checkCondition,\r
+ Object constraintText,\r
+ Object behavior)\r
+ {\r
+ this.constraintName = (TableName) constraintName;\r
+\r
+ /* We need to pass null as name to TableElementNode's constructor \r
+ * since constraintName may be null.\r
+ */\r
+ super.init(null);\r
+ if (this.constraintName != null)\r
+ {\r
+ this.name = this.constraintName.getTableName();\r
+ }\r
+ this.constraintType = ((Integer) constraintType).intValue();\r
+ this.properties = (Properties) properties;\r
+ this.columnList = (ResultColumnList) rcl;\r
+ this.checkCondition = (ValueNode) checkCondition;\r
+ this.constraintText = (String) constraintText;\r
+ this.behavior = ((Integer) behavior).intValue();\r
+ }\r
+\r
+ public void init(\r
+ Object constraintName,\r
+ Object constraintType,\r
+ Object rcl,\r
+ Object properties,\r
+ Object checkCondition,\r
+ Object constraintText)\r
+ {\r
+ init(\r
+ constraintName,\r
+ constraintType,\r
+ rcl,\r
+ properties, \r
+ checkCondition,\r
+ constraintText,\r
+ ReuseFactory.getInteger(StatementType.DROP_DEFAULT)\r
+ );\r
+ }\r
+\r
+ public void init(\r
+ Object constraintName,\r
+ Object constraintType,\r
+ Object rcl,\r
+ Object properties,\r
+ Object checkCondition,\r
+ Object constraintText,\r
+ Object behavior,\r
+ Object verifyType)\r
+ {\r
+ init( constraintName, constraintType, rcl, properties, checkCondition, constraintText, behavior);\r
+ this.verifyType = ((Integer) verifyType).intValue();\r
+ }\r
+ \r
+ /**\r
+ * Convert this object to a String. See comments in QueryTreeNode.java\r
+ * for how this should be done for tree printing.\r
+ *\r
+ * @return This object as a String\r
+ */\r
+\r
+ public String toString()\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ return "constraintName: " + \r
+ ( ( constraintName != null) ?\r
+ constraintName.toString() : "null" ) + "\n" +\r
+ "constraintType: " + constraintType + "\n" + \r
+ "properties: " +\r
+ ((properties != null) ? properties.toString() : "null") + "\n" +\r
+ super.toString();\r
+ }\r
+ else\r
+ {\r
+ return "";\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Bind this constraint definition. \r
+ *\r
+ @param ddlNode the create or alter table node\r
+ * @param dd the dd\r
+ *\r
+ * @exception StandardException on error\r
+ */\r
+ protected void bind(DDLStatementNode ddlNode, DataDictionary dd) throws StandardException\r
+ {\r
+ // we need to allow drops on constraints with different schemas\r
+ // to support removing constraints created pre 5.2.\r
+ if (constraintType == DataDictionary.DROP_CONSTRAINT)\r
+ return;\r
+\r
+ // ensure the schema of the constraint matches the schema of the table\r
+ if (constraintName != null) {\r
+\r
+ String constraintSchema = constraintName.getSchemaName();\r
+\r
+\r
+ if (constraintSchema != null) {\r
+\r
+\r
+\r
+ TableName tableName = ddlNode.getObjectName();\r
+ String tableSchema = tableName.getSchemaName();\r
+ if (tableSchema == null) {\r
+ tableSchema = getSchemaDescriptor((String) null).getSchemaName();\r
+ tableName.setSchemaName(tableSchema);\r
+ }\r
+ if (!constraintSchema.equals(tableSchema)) {\r
+ throw StandardException.newException(SQLState.LANG_CONSTRAINT_SCHEMA_MISMATCH,\r
+ constraintName, tableName);\r
+\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ name = getBackingIndexName(dd);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Get the name of the constraint. If the user didn't provide one, we make one up. This allows Replication\r
+ * to agree with the core compiler on the names of constraints.\r
+ *\r
+ * @return constraint name\r
+ */\r
+ String getConstraintMoniker()\r
+ {\r
+ return name;\r
+ }\r
+\r
+ /**\r
+ To support dropping exisiting constraints that may have mismatched schema names\r
+ we need to support ALTER TABLE S1.T DROP CONSTRAINT S2.C.\r
+ If a constraint name was specified this returns it, otherwise it returns null.\r
+ */\r
+ String getDropSchemaName() {\r
+ if (constraintName != null)\r
+ return constraintName.getSchemaName();\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Allocates a UUID if one doesn't already exist for the index backing this constraint. This allows Replication\r
+ * logic to agree with the core compiler on what the UUIDs of indices are.\r
+ *\r
+ * @return a UUID for the constraint. allocates one if this is the first time this method is called.\r
+ */\r
+ UUID getBackingIndexUUID()\r
+ {\r
+ if ( backingIndexUUID == null )\r
+ {\r
+ backingIndexUUID = getUUIDFactory().createUUID();\r
+ }\r
+\r
+ return backingIndexUUID;\r
+ }\r
+\r
+ /**\r
+ * Gets a unique name for the backing index for this constraint of the form SQLyymmddhhmmssxxn\r
+ * yy - year, mm - month, dd - day of month, hh - hour, mm - minute, ss - second,\r
+ * xx - the first 2 digits of millisec because we don't have enough space to keep the exact millisec value,\r
+ * n - number between 0-9\r
+ *\r
+ * @return name of backing index\r
+ */\r
+ String getBackingIndexName(DataDictionary dd)\r
+ {\r
+ if ( backingIndexName == null )\r
+ backingIndexName = dd.getSystemSQLName();\r
+\r
+ return backingIndexName;\r
+ }\r
+\r
+ /**\r
+ * Set the auxiliary provider list.\r
+ *\r
+ * @param apl The new auxiliary provider list.\r
+ */\r
+ void setAuxiliaryProviderList(ProviderList apl)\r
+ {\r
+ this.apl = apl;\r
+ }\r
+\r
+ /**\r
+ * Return the auxiliary provider list.\r
+ *\r
+ * @return The auxiliary provider list.\r
+ */\r
+ public ProviderList getAuxiliaryProviderList()\r
+ {\r
+ return apl;\r
+ }\r
+\r
+ /**\r
+ * Is this a primary key constraint.\r
+ *\r
+ * @return boolean Whether or not this is a primary key constraint\r
+ */\r
+ boolean hasPrimaryKeyConstraint()\r
+ {\r
+ return constraintType == DataDictionary.PRIMARYKEY_CONSTRAINT;\r
+ }\r
+\r
+ /**\r
+ * Is this a unique key constraint.\r
+ *\r
+ * @return boolean Whether or not this is a unique key constraint\r
+ */\r
+ boolean hasUniqueKeyConstraint()\r
+ {\r
+ return constraintType == DataDictionary.UNIQUE_CONSTRAINT;\r
+ }\r
+\r
+ /**\r
+ * Is this a foreign key constraint.\r
+ *\r
+ * @return boolean Whether or not this is a unique key constraint\r
+ */\r
+ boolean hasForeignKeyConstraint()\r
+ {\r
+ return constraintType == DataDictionary.FOREIGNKEY_CONSTRAINT;\r
+ }\r
+\r
+ /**\r
+ * Does this element have a check constraint.\r
+ *\r
+ * @return boolean Whether or not this element has a check constraint\r
+ */\r
+ boolean hasCheckConstraint()\r
+ {\r
+ return constraintType == DataDictionary.CHECK_CONSTRAINT;\r
+ }\r
+\r
+ /**\r
+ * Does this element have a constraint on it.\r
+ *\r
+ * @return boolean Whether or not this element has a constraint on it\r
+ */\r
+ boolean hasConstraint()\r
+ {\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Is this a foreign key constraint.\r
+ *\r
+ * @return boolean Whether or not this is a unique key constraint\r
+ */\r
+ boolean requiresBackingIndex()\r
+ {\r
+ switch (constraintType)\r
+ {\r
+ case DataDictionary.FOREIGNKEY_CONSTRAINT:\r
+ case DataDictionary.PRIMARYKEY_CONSTRAINT:\r
+ case DataDictionary.UNIQUE_CONSTRAINT:\r
+ return true;\r
+ default:\r
+ return false;\r
+ }\r
+ } \r
+\r
+ /**\r
+ * Is this a foreign key constraint.\r
+ *\r
+ * @return boolean Whether or not this is a unique key constraint\r
+ */\r
+ boolean requiresUniqueIndex()\r
+ {\r
+ switch (constraintType)\r
+ {\r
+ case DataDictionary.PRIMARYKEY_CONSTRAINT:\r
+ case DataDictionary.UNIQUE_CONSTRAINT:\r
+ return true;\r
+ default:\r
+ return false;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Get the constraint type\r
+ *\r
+ * @return constraintType The constraint type.\r
+ */\r
+ int getConstraintType()\r
+ {\r
+ return constraintType;\r
+ }\r
+\r
+ /**\r
+ * Set the optional properties for the backing index to this constraint.\r
+ *\r
+ * @param properties The optional Properties for this constraint.\r
+ */\r
+ public void setProperties(Properties properties)\r
+ {\r
+ this.properties = properties;\r
+ }\r
+\r
+ /** \r
+ * Get the optional properties for the backing index to this constraint.\r
+ *\r
+ *\r
+ * @return The optional properties for the backing index to this constraint\r
+ */\r
+ public Properties getProperties()\r
+ {\r
+ return properties;\r
+ }\r
+\r
+\r
+ /** \r
+ * Is this constraint referenced.\r
+ *\r
+ * @return true/false\r
+ */\r
+ public boolean isReferenced()\r
+ {\r
+ return false;\r
+ }\r
+\r
+ /** \r
+ * Get the count of enabled fks\r
+ * that reference this constraint\r
+ *\r
+ * @return the number\r
+ */\r
+ public int getReferenceCount()\r
+ {\r
+ return 0;\r
+ }\r
+ /** \r
+ * Is this constraint enabled.\r
+ *\r
+ * @return true/false\r
+ */\r
+ public boolean isEnabled()\r
+ {\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Get the column list from this node.\r
+ *\r
+ * @return ResultColumnList The column list from this table constraint.\r
+ */\r
+ public ResultColumnList getColumnList()\r
+ {\r
+ return columnList;\r
+ }\r
+\r
+ /**\r
+ * Set the column list for this node. This is useful for check constraints\r
+ * where the list of referenced columns is built at bind time.\r
+ *\r
+ * @param columnList The new columnList.\r
+ */\r
+ public void setColumnList(ResultColumnList columnList)\r
+ {\r
+ this.columnList = columnList;\r
+ }\r
+\r
+ /**\r
+ * Get the check condition from this table constraint.\r
+ *\r
+ * @return The check condition from this node.\r
+ */\r
+ public ValueNode getCheckCondition()\r
+ {\r
+ return checkCondition;\r
+ }\r
+\r
+ /**\r
+ * Set the check condition for this table constraint.\r
+ *\r
+ * @param checkCondition The check condition\r
+ */\r
+ public void setCheckCondition(ValueNode checkCondition)\r
+ {\r
+ this.checkCondition = checkCondition;\r
+ }\r
+\r
+ /**\r
+ * Get the text of the constraint. (Only meaningful for check constraints.)\r
+ *\r
+ * @return The constraint text.\r
+ */\r
+ public String getConstraintText()\r
+ {\r
+ return constraintText;\r
+ }\r
+\r
+ /**\r
+ * Get the array of 1-based column references for a check constraint.\r
+ *\r
+ * @return The array of 1-based column references for a check constraint.\r
+ */\r
+ public int[] getCheckColumnReferences()\r
+ {\r
+ return checkColumnReferences;\r
+ }\r
+\r
+ /**\r
+ * Set the array of 1-based column references for a check constraint.\r
+ *\r
+ * @param checkColumnReferences The array of 1-based column references\r
+ * for the check constraint.\r
+ */\r
+ public void setCheckColumnReferences(int[] checkColumnReferences)\r
+ {\r
+ this.checkColumnReferences = checkColumnReferences;\r
+ }\r
+\r
+ /**\r
+ * Return the behavior of this constriant (DropStatementNode.xxx) \r
+ *\r
+ * @return the behavior\r
+ */\r
+ int getDropBehavior()\r
+ {\r
+ return behavior;\r
+ }\r
+\r
+ /**\r
+ * @return the expected type of the constraint, DataDictionary.DROP_CONSTRAINT if the constraint is\r
+ * to be dropped without checking its type.\r
+ */\r
+ int getVerifyType()\r
+ {\r
+ return verifyType;\r
+ }\r
+\r
+ ///////////////////////////////////////////////////////////////////////////\r
+ //\r
+ // MINIONS\r
+ //\r
+ ///////////////////////////////////////////////////////////////////////////\r
+ /**\r
+ * Get the UUID factory\r
+ *\r
+ * @return the UUID factory\r
+ *\r
+ */\r
+ private UUIDFactory getUUIDFactory()\r
+ {\r
+ if ( uuidFactory == null )\r
+ {\r
+ uuidFactory = Monitor.getMonitor().getUUIDFactory();\r
+ }\r
+ return uuidFactory;\r
+ }\r
+}\r