--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.execute.DropConstraintConstantAction\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.execute;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.services.io.FormatableHashtable;\r
+\r
+import org.apache.derby.catalog.UUID;\r
+import org.apache.derby.iapi.services.uuid.UUIDFactory;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;\r
+\r
+import org.apache.derby.iapi.sql.StatementType;\r
+\r
+import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList;\r
+import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator;\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+import org.apache.derby.iapi.sql.dictionary.ForeignKeyConstraintDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.ReferencedKeyConstraintDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;\r
+\r
+import org.apache.derby.iapi.types.DataValueFactory;\r
+\r
+import org.apache.derby.iapi.sql.depend.DependencyManager;\r
+\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.iapi.sql.execute.ConstantAction;\r
+\r
+import org.apache.derby.iapi.sql.Activation;\r
+\r
+import org.apache.derby.iapi.store.access.TransactionController;\r
+\r
+import org.apache.derby.catalog.UUID;\r
+\r
+/**\r
+ * This class describes actions that are ALWAYS performed for a\r
+ * drop constraint at Execution time.\r
+ *\r
+ * @version 0.1\r
+ */\r
+\r
+public class DropConstraintConstantAction extends ConstraintConstantAction\r
+{\r
+\r
+ private boolean cascade; // default false\r
+ private String constraintSchemaName;\r
+ private int verifyType;\r
+\r
+ // CONSTRUCTORS\r
+\r
+ /**\r
+ * Make one of these puppies.\r
+ *\r
+ * @param constraintName Constraint name.\r
+ * @param constraintSchemaName the schema that constraint lives in.\r
+ * @param tableName Table name.\r
+ * @param tableId UUID of table.\r
+ * @param tableSchemaName the schema that table lives in.\r
+ * @param indexAction IndexConstantAction for constraint (if necessary)\r
+ * @param behavior the drop behavior (e.g. StatementType.DROP_CASCADE)\r
+ */\r
+ DropConstraintConstantAction(\r
+ String constraintName,\r
+ String constraintSchemaName,\r
+ String tableName,\r
+ UUID tableId,\r
+ String tableSchemaName,\r
+ IndexConstantAction indexAction,\r
+ int behavior,\r
+ int verifyType)\r
+ {\r
+ super(constraintName, DataDictionary.DROP_CONSTRAINT, tableName, \r
+ tableId, tableSchemaName, indexAction);\r
+\r
+ cascade = (behavior == StatementType.DROP_CASCADE);\r
+ this.constraintSchemaName = constraintSchemaName;\r
+ this.verifyType = verifyType;\r
+ }\r
+\r
+ // OBJECT METHODS\r
+\r
+ public String toString()\r
+ {\r
+ // Do not put this under SanityManager.DEBUG - it is needed for\r
+ // error reporting.\r
+ if (constraintName == null)\r
+ return "DROP PRIMARY KEY";\r
+\r
+ String ss = constraintSchemaName == null ? schemaName : constraintSchemaName;\r
+ return "DROP CONSTRAINT " + ss + "." + constraintName;\r
+ }\r
+\r
+ // INTERFACE METHODS\r
+\r
+\r
+ /**\r
+ * This is the guts of the Execution-time logic for DROP CONSTRAINT.\r
+ *\r
+ * @see ConstantAction#executeConstantAction\r
+ *\r
+ * @exception StandardException Thrown on failure\r
+ */\r
+ public void executeConstantAction( Activation activation )\r
+ throws StandardException\r
+ {\r
+ ConstraintDescriptor conDesc = null;\r
+ TableDescriptor td;\r
+ UUID indexId = null;\r
+ String indexUUIDString;\r
+\r
+ LanguageConnectionContext lcc = activation.getLanguageConnectionContext();\r
+ DataDictionary dd = lcc.getDataDictionary();\r
+ DependencyManager dm = dd.getDependencyManager();\r
+ TransactionController tc = lcc.getTransactionExecute();\r
+\r
+\r
+ /*\r
+ ** Inform the data dictionary that we are about to write to it.\r
+ ** There are several calls to data dictionary "get" methods here\r
+ ** that might be done in "read" mode in the data dictionary, but\r
+ ** it seemed safer to do this whole operation in "write" mode.\r
+ **\r
+ ** We tell the data dictionary we're done writing at the end of\r
+ ** the transaction.\r
+ */\r
+ dd.startWriting(lcc);\r
+\r
+ td = dd.getTableDescriptor(tableId);\r
+\r
+ if (td == null)\r
+ {\r
+ throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tableName);\r
+ }\r
+\r
+ /* Table gets locked in AlterTableConstantAction */\r
+\r
+ /*\r
+ ** If the schema descriptor is null, then\r
+ ** we must have just read ourselves in. \r
+ ** So we will get the corresponding schema\r
+ ** descriptor from the data dictionary.\r
+ */\r
+\r
+ SchemaDescriptor tdSd = td.getSchemaDescriptor();\r
+ SchemaDescriptor constraintSd = \r
+ constraintSchemaName == null ? tdSd : dd.getSchemaDescriptor(constraintSchemaName, tc, true);\r
+\r
+\r
+ /* Get the constraint descriptor for the index, along\r
+ * with an exclusive row lock on the row in sys.sysconstraints\r
+ * in order to ensure that no one else compiles against the\r
+ * index.\r
+ */\r
+ if (constraintName == null) // this means "alter table drop primary key"\r
+ conDesc = dd.getConstraintDescriptors(td).getPrimaryKey();\r
+ else\r
+ conDesc = dd.getConstraintDescriptorByName(td, constraintSd, constraintName, true);\r
+\r
+ // Error if constraint doesn't exist\r
+ if (conDesc == null)\r
+ {\r
+ String errorName = constraintName == null ? "PRIMARY KEY" :\r
+ (constraintSd.getSchemaName() + "."+ constraintName);\r
+\r
+ throw StandardException.newException(SQLState.LANG_DROP_NON_EXISTENT_CONSTRAINT, \r
+ errorName,\r
+ td.getQualifiedName());\r
+ }\r
+ switch( verifyType)\r
+ {\r
+ case DataDictionary.UNIQUE_CONSTRAINT:\r
+ if( conDesc.getConstraintType() != verifyType)\r
+ throw StandardException.newException(SQLState.LANG_DROP_CONSTRAINT_TYPE,\r
+ constraintName, "UNIQUE");\r
+ break;\r
+\r
+ case DataDictionary.CHECK_CONSTRAINT:\r
+ if( conDesc.getConstraintType() != verifyType)\r
+ throw StandardException.newException(SQLState.LANG_DROP_CONSTRAINT_TYPE,\r
+ constraintName, "CHECK");\r
+ break;\r
+\r
+ case DataDictionary.FOREIGNKEY_CONSTRAINT:\r
+ if( conDesc.getConstraintType() != verifyType)\r
+ throw StandardException.newException(SQLState.LANG_DROP_CONSTRAINT_TYPE,\r
+ constraintName, "FOREIGN KEY");\r
+ break;\r
+ }\r
+\r
+ boolean cascadeOnRefKey = (cascade && \r
+ conDesc instanceof ReferencedKeyConstraintDescriptor);\r
+ if (!cascadeOnRefKey)\r
+ {\r
+ dm.invalidateFor(conDesc, DependencyManager.DROP_CONSTRAINT, lcc);\r
+ }\r
+\r
+ /*\r
+ ** If we had a primary/unique key and it is drop cascade, \r
+ ** drop all the referencing keys now. We MUST do this AFTER\r
+ ** dropping the referenced key because otherwise we would\r
+ ** be repeatedly changing the reference count of the referenced\r
+ ** key and generating unnecessary I/O.\r
+ */\r
+ conDesc.drop(lcc, !cascadeOnRefKey);\r
+\r
+ if (cascadeOnRefKey) \r
+ {\r
+ ForeignKeyConstraintDescriptor fkcd;\r
+ ReferencedKeyConstraintDescriptor cd;\r
+ ConstraintDescriptorList cdl;\r
+\r
+ cd = (ReferencedKeyConstraintDescriptor)conDesc;\r
+ cdl = cd.getForeignKeyConstraints(ReferencedKeyConstraintDescriptor.ALL);\r
+ int cdlSize = cdl.size();\r
+\r
+ for(int index = 0; index < cdlSize; index++)\r
+ {\r
+ fkcd = (ForeignKeyConstraintDescriptor) cdl.elementAt(index);\r
+ dm.invalidateFor(fkcd, DependencyManager.DROP_CONSTRAINT, lcc);\r
+ fkcd.drop(lcc, true);\r
+ }\r
+ \r
+ /*\r
+ ** We told dropConstraintAndIndex not to\r
+ ** remove our dependencies, so send an invalidate,\r
+ ** and drop the dependencies.\r
+ */\r
+ dm.invalidateFor(conDesc, DependencyManager.DROP_CONSTRAINT, lcc);\r
+ dm.clearDependencies(lcc, conDesc);\r
+ }\r
+ }\r
+}\r