Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / derby-10.3.2.1 / java / engine / org / apache / derby / impl / sql / execute / CreateConstraintConstantAction.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/execute/CreateConstraintConstantAction.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/execute/CreateConstraintConstantAction.java
new file mode 100644 (file)
index 0000000..063a13c
--- /dev/null
@@ -0,0 +1,533 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.execute.CreateConstraintConstantAction\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
+\r
+import org.apache.derby.catalog.UUID;\r
+import org.apache.derby.iapi.services.uuid.UUIDFactory;\r
+import org.apache.derby.catalog.types.ReferencedColumnsDescriptorImpl;\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.dictionary.DDUtils;\r
+import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;\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.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.reference.SQLState;\r
+\r
+import org.apache.derby.iapi.sql.depend.DependencyManager;\r
+import org.apache.derby.iapi.sql.depend.Provider;\r
+import org.apache.derby.iapi.sql.depend.ProviderInfo;\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
+import org.apache.derby.iapi.services.loader.ClassFactory;\r
+\r
+/**\r
+ *     This class  describes actions that are ALWAYS performed for a\r
+ *     constraint creation at Execution time.\r
+ *\r
+ *     @version 0.1\r
+ */\r
+\r
+public class CreateConstraintConstantAction extends ConstraintConstantAction\r
+{\r
+       String[]                columnNames;\r
+       private String                  constraintText;\r
+\r
+       private ConstraintInfo  otherConstraintInfo;\r
+       private ClassFactory    cf;\r
+\r
+       /*\r
+       ** Is this constraint to be created as enabled or not.\r
+       ** The only way to create a disabled constraint is by\r
+       ** publishing a disabled constraint.\r
+       */\r
+       private boolean                 enabled;\r
+\r
+       private ProviderInfo[] providerInfo;\r
+\r
+       // CONSTRUCTORS\r
+\r
+       /**\r
+        *      Make one of these puppies.\r
+        *\r
+        *  @param constraintName       Constraint name.\r
+        *  @param constraintType       Constraint type.\r
+        *  @param tableName            Table name.\r
+        *      @param tableId                  UUID of table.\r
+        *  @param schemaName           the schema that table and constraint lives in.\r
+        *  @param columnNames          String[] for column names\r
+        *  @param indexAction          IndexConstantAction for constraint (if necessary)\r
+        *  @param constraintText       Text for check constraint\r
+        *  RESOLVE - the next parameter should go away once we use UUIDs\r
+        *                        (Generated constraint names will be based off of uuids)\r
+        *      @param enabled                  Should the constraint be created as enabled \r
+        *                                                      (enabled == true), or disabled (enabled == false).\r
+        *      @param otherConstraint  information about the constraint that this references\r
+        *  @param providerInfo Information on all the Providers\r
+        */\r
+       CreateConstraintConstantAction(\r
+                              String   constraintName,\r
+                                          int          constraintType,\r
+                              String   tableName,\r
+                                          UUID         tableId,\r
+                                          String       schemaName,\r
+                                          String[]     columnNames,\r
+                                          IndexConstantAction indexAction,\r
+                                          String       constraintText,\r
+                                          boolean      enabled,\r
+                                      ConstraintInfo   otherConstraint,\r
+                                          ProviderInfo[] providerInfo)\r
+       {\r
+               super(constraintName, constraintType, tableName, \r
+                         tableId, schemaName, indexAction);\r
+               this.columnNames = columnNames;\r
+               this.constraintText = constraintText;\r
+               this.enabled = enabled;\r
+               this.otherConstraintInfo = otherConstraint;\r
+               this.providerInfo = providerInfo;\r
+       }\r
+\r
+       // INTERFACE METHODS\r
+\r
+\r
+       /**\r
+        *      This is the guts of the Execution-time logic for CREATE CONSTRAINT.\r
+        *  <P>\r
+        *  A constraint is represented as:\r
+        *  <UL>\r
+        *  <LI> ConstraintDescriptor.\r
+        *  </UL>\r
+        *  If a backing index is required then the index will\r
+        *  be created through an CreateIndexConstantAction setup\r
+        *  by the compiler.\r
+        *  <BR>\r
+        *  Dependencies are created as:\r
+        *  <UL>\r
+        *  <LI> ConstraintDescriptor depends on all the providers collected\r
+     *  at compile time and passed into the constructor.\r
+        *  <LI> For a FOREIGN KEY constraint ConstraintDescriptor depends\r
+     *  on the ConstraintDescriptor for the referenced constraints\r
+     *  and the privileges required to create the constraint.\r
+        *  </UL>\r
+\r
+        *  @see ConstraintDescriptor\r
+        *  @see CreateIndexConstantAction\r
+        *      @see ConstantAction#executeConstantAction\r
+        *\r
+        * @exception StandardException         Thrown on failure\r
+        */\r
+       public void     executeConstantAction( Activation activation )\r
+                                               throws StandardException\r
+       {\r
+               boolean                                         forCreateTable;\r
+               ConglomerateDescriptor          conglomDesc = null;\r
+               ConglomerateDescriptor[]        conglomDescs = null;\r
+               ConstraintDescriptor            conDesc = null;\r
+               TableDescriptor                         td = null;\r
+               UUID                                            indexId = null;\r
+               String                                          uniqueName;\r
+               String                                          backingIndexName;\r
+\r
+               /* RESOLVE - blow off not null constraints for now (and probably for ever) */\r
+               if (constraintType == DataDictionary.NOTNULL_CONSTRAINT)\r
+               {\r
+                       return;\r
+               }\r
+\r
+               LanguageConnectionContext lcc = activation.getLanguageConnectionContext();\r
+               DataDictionary dd = lcc.getDataDictionary();\r
+               DependencyManager dm = dd.getDependencyManager();\r
+               TransactionController tc = lcc.getTransactionExecute();\r
+\r
+               cf = lcc.getLanguageConnectionFactory().getClassFactory();\r
+\r
+               /* Remember whether or not we are doing a create table */\r
+               forCreateTable = activation.getForCreateTable();\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
+               /* 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 sd = dd.getSchemaDescriptor(schemaName, tc, true);\r
+               \r
+               /* Try to get the TableDescriptor from\r
+                * the Activation. We will go to the\r
+                * DD if not there. (It should always be\r
+                * there except when in a target.)\r
+                */\r
+               td = activation.getDDLTableDescriptor();\r
+\r
+               if (td == null)\r
+               {\r
+                       /* tableId will be non-null if adding a\r
+                        * constraint to an existing table.\r
+                        */\r
+                       if (tableId != null)\r
+                       {\r
+                               td = dd.getTableDescriptor(tableId);\r
+                       }\r
+                       else\r
+                       {\r
+                               td = dd.getTableDescriptor(tableName, sd);\r
+                       }\r
+\r
+                       if (td == null)\r
+                       {\r
+                               throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tableName);\r
+                       }\r
+                       activation.setDDLTableDescriptor(td);\r
+               }\r
+\r
+               /* Generate the UUID for the backing index.  This will become the\r
+                * constraint's name, if no name was specified.\r
+                */\r
+               UUIDFactory uuidFactory = dd.getUUIDFactory();\r
+        \r
+               /* Create the index, if there's one for this constraint */\r
+               if (indexAction != null)\r
+               {\r
+                       if ( indexAction.getIndexName() == null )\r
+                       {\r
+                               /* Set the index name */\r
+                               backingIndexName =  uuidFactory.createUUID().toString();\r
+                               indexAction.setIndexName(backingIndexName);\r
+                       }\r
+                       else { backingIndexName = indexAction.getIndexName(); }\r
+\r
+\r
+                       /* Create the index */\r
+                       indexAction.executeConstantAction(activation);\r
+\r
+                       /* Get the conglomerate descriptor for the backing index */\r
+                       conglomDescs = td.getConglomerateDescriptors();\r
+\r
+                       for (int index = 0; index < conglomDescs.length; index++)\r
+                       {\r
+                               conglomDesc = conglomDescs[index];\r
+\r
+                               /* Check for conglomerate being an index first, since\r
+                                * name is null for heap.\r
+                                */\r
+                               if (conglomDesc.isIndex() && \r
+                                       backingIndexName.equals(conglomDesc.getConglomerateName()))\r
+                               {\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       if (SanityManager.DEBUG)\r
+                       {\r
+                               SanityManager.ASSERT(conglomDesc != null,\r
+                                       "conglomDesc is expected to be non-null after search for backing index");\r
+                               SanityManager.ASSERT(conglomDesc.isIndex(),\r
+                                       "conglomDesc is expected to be indexable after search for backing index");\r
+                               SanityManager.ASSERT(conglomDesc.getConglomerateName().equals(backingIndexName),\r
+                          "conglomDesc name expected to be the same as backing index name after search for backing index");\r
+                       }\r
+\r
+                       indexId = conglomDesc.getUUID();\r
+               }\r
+\r
+               UUID constraintId = uuidFactory.createUUID();\r
+\r
+               /* Now, lets create the constraint descriptor */\r
+               DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();\r
+               switch (constraintType)\r
+               {\r
+                       case DataDictionary.PRIMARYKEY_CONSTRAINT:\r
+                               conDesc = ddg.newPrimaryKeyConstraintDescriptor(\r
+                                                               td, constraintName,\r
+                                                               false, //deferable,\r
+                                                               false, //initiallyDeferred,\r
+                                                               genColumnPositions(td, false), //int[],\r
+                                                               constraintId, \r
+                                                               indexId, \r
+                                                               sd,\r
+                                                               enabled,\r
+                                                               0                               // referenceCount\r
+                                                               );\r
+                               dd.addConstraintDescriptor(conDesc, tc);\r
+                               break;\r
+\r
+                       case DataDictionary.UNIQUE_CONSTRAINT:\r
+                               conDesc = ddg.newUniqueConstraintDescriptor(\r
+                                                               td, constraintName,\r
+                                                               false, //deferable,\r
+                                                               false, //initiallyDeferred,\r
+                                                               genColumnPositions(td, false), //int[],\r
+                                                               constraintId, \r
+                                                               indexId, \r
+                                                               sd,\r
+                                                               enabled,\r
+                                                               0                               // referenceCount\r
+                                                               );\r
+                               dd.addConstraintDescriptor(conDesc, tc);\r
+                               break;\r
+\r
+                       case DataDictionary.CHECK_CONSTRAINT:\r
+                               conDesc = ddg.newCheckConstraintDescriptor(\r
+                                                               td, constraintName,\r
+                                                               false, //deferable,\r
+                                                               false, //initiallyDeferred,\r
+                                                               constraintId, \r
+                                                               constraintText, \r
+                                                               new ReferencedColumnsDescriptorImpl(genColumnPositions(td, false)), //int[],\r
+                                                               sd,\r
+                                                               enabled\r
+                                                               );\r
+                               dd.addConstraintDescriptor(conDesc, tc);\r
+                               break;\r
+\r
+                       case DataDictionary.FOREIGNKEY_CONSTRAINT:\r
+                               ReferencedKeyConstraintDescriptor referencedConstraint = DDUtils.locateReferencedConstraint\r
+                                       ( dd, td, constraintName, columnNames, otherConstraintInfo );\r
+                               DDUtils.validateReferentialActions(dd, td, constraintName, otherConstraintInfo,columnNames);\r
+                               \r
+                               conDesc = ddg.newForeignKeyConstraintDescriptor(\r
+                                                               td, constraintName,\r
+                                                               false, //deferable,\r
+                                                               false, //initiallyDeferred,\r
+                                                               genColumnPositions(td, false), //int[],\r
+                                                               constraintId,\r
+                                                               indexId,\r
+                                                               sd,\r
+                                                               referencedConstraint,\r
+                                                               enabled,\r
+                                                               otherConstraintInfo.getReferentialActionDeleteRule(),\r
+                                                               otherConstraintInfo.getReferentialActionUpdateRule()\r
+                                                               );\r
+\r
+                               // try to create the constraint first, because it\r
+                               // is expensive to do the bulk check, find obvious\r
+                               // errors first\r
+                               dd.addConstraintDescriptor(conDesc, tc);\r
+\r
+                               /* No need to do check if we're creating a \r
+                                * table.\r
+                                */\r
+                               if ( (! forCreateTable) && \r
+                                        dd.activeConstraint( conDesc ) )\r
+                               {\r
+                                       validateFKConstraint(tc, \r
+                                                                                dd, \r
+                                                                                (ForeignKeyConstraintDescriptor)conDesc, \r
+                                                                                referencedConstraint,\r
+                                                                                ((CreateIndexConstantAction)indexAction).getIndexTemplateRow());\r
+                               }\r
+                               \r
+                               /* Create stored dependency on the referenced constraint */\r
+                               dm.addDependency(conDesc, referencedConstraint, lcc.getContextManager());\r
+                               //store constraint's dependency on REFERENCES privileges in the dependeny system\r
+                               storeConstraintDependenciesOnPrivileges(activation, conDesc, referencedConstraint.getTableId());                                \r
+                               break;\r
+\r
+                       default:\r
+                               if (SanityManager.DEBUG)\r
+                               {\r
+                                       SanityManager.THROWASSERT("contraintType (" + constraintType + \r
+                                               ") has unexpected value");\r
+                               }\r
+                               break;\r
+               }\r
+\r
+               /* Create stored dependencies for each provider */\r
+               if (providerInfo != null)\r
+               {\r
+                       for (int ix = 0; ix < providerInfo.length; ix++)\r
+                       {\r
+                               Provider provider = null;\r
+       \r
+                               /* We should always be able to find the Provider */\r
+                                       provider = (Provider) providerInfo[ix].\r
+                                                                                       getDependableFinder().\r
+                                                                                               getDependable(dd, \r
+                                                                                                       providerInfo[ix].getObjectId());\r
+\r
+                               dm.addDependency(conDesc, provider, lcc.getContextManager());\r
+                       }\r
+               }\r
+\r
+               /* Finally, invalidate off of the table descriptor(s)\r
+                * to ensure that any dependent statements get\r
+                * re-compiled.\r
+                */\r
+               if (! forCreateTable)\r
+               {\r
+                       dm.invalidateFor(td, DependencyManager.CREATE_CONSTRAINT, lcc);\r
+               }\r
+               if (constraintType == DataDictionary.FOREIGNKEY_CONSTRAINT)\r
+               {\r
+                       if (SanityManager.DEBUG)\r
+                       {\r
+                               SanityManager.ASSERT(conDesc != null,\r
+                                       "conDesc expected to be non-null");\r
+\r
+                               if (! (conDesc instanceof ForeignKeyConstraintDescriptor))\r
+                               {\r
+                                       SanityManager.THROWASSERT(\r
+                                               "conDesc expected to be instance of ForeignKeyConstraintDescriptor, not " +\r
+                                               conDesc.getClass().getName());\r
+                               }\r
+                       }\r
+                       dm.invalidateFor(\r
+                               ((ForeignKeyConstraintDescriptor)conDesc).\r
+                                       getReferencedConstraint().\r
+                                               getTableDescriptor(),\r
+                               DependencyManager.CREATE_CONSTRAINT, lcc);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Is the constant action for a foreign key\r
+        *\r
+        * @return true/false\r
+        */\r
+       boolean isForeignKeyConstraint()\r
+       { \r
+               return (constraintType == DataDictionary.FOREIGNKEY_CONSTRAINT);\r
+       }\r
+\r
+       /**\r
+        * Generate an array of column positions for the column list in\r
+        * the constraint.\r
+        *\r
+        * @param td    The TableDescriptor for the table in question\r
+        * @param columnsMustBeOrderable        true for primaryKey and unique constraints\r
+        *\r
+        * @return int[]        The column positions.\r
+        */\r
+       private int[] genColumnPositions(TableDescriptor td,\r
+                                                                        boolean columnsMustBeOrderable)\r
+               throws StandardException\r
+       {\r
+               int[] baseColumnPositions;\r
+\r
+               // Translate the base column names to column positions\r
+               baseColumnPositions = new int[columnNames.length];\r
+               for (int i = 0; i < columnNames.length; i++)\r
+               {\r
+                       ColumnDescriptor columnDescriptor;\r
+\r
+                       // Look up the column in the data dictionary\r
+                       columnDescriptor = td.getColumnDescriptor(columnNames[i]);\r
+                       if (columnDescriptor == null)\r
+                       {\r
+                               throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE, \r
+                                                                                                                       columnNames[i],\r
+                                                                                                                       tableName);\r
+                       }\r
+\r
+                       // Don't allow a column to be created on a non-orderable type\r
+                       // (for primaryKey and unique constraints)\r
+                       if ( columnsMustBeOrderable &&\r
+                                ( ! columnDescriptor.getType().getTypeId().orderable(\r
+                                                                                                                       cf))\r
+                          )\r
+                       {\r
+                               throw StandardException.newException(SQLState.LANG_COLUMN_NOT_ORDERABLE_DURING_EXECUTION, \r
+                                       columnDescriptor.getType().getTypeId().getSQLTypeName());\r
+                       }\r
+\r
+                       // Remember the position in the base table of each column\r
+                       baseColumnPositions[i] = columnDescriptor.getPosition();\r
+               }\r
+\r
+               return baseColumnPositions;\r
+       }\r
+       ///////////////////////////////////////////////////////////////////////\r
+       //\r
+       //      ACCESSORS\r
+       //\r
+       ///////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+       /**\r
+         *     Get the text defining this constraint.\r
+         *\r
+         *     @return constraint text\r
+         */\r
+    String     getConstraintText() { return constraintText; }\r
+\r
+       public String toString()\r
+       {\r
+               // Do not put this under SanityManager.DEBUG - it is needed for\r
+               // error reporting.\r
+               StringBuffer strbuf = new StringBuffer();\r
+               strbuf.append( "CREATE CONSTRAINT " + constraintName );\r
+               strbuf.append("\n=========================\n");\r
+\r
+               if (columnNames == null)\r
+               {\r
+                       strbuf.append("columnNames == null\n");\r
+               }\r
+               else\r
+               {\r
+                       for (int ix=0; ix < columnNames.length; ix++)\r
+                       {\r
+                               strbuf.append("\n\tcol["+ix+"]"+columnNames[ix].toString());\r
+                       }\r
+               }\r
+               \r
+               strbuf.append("\n");\r
+               strbuf.append(constraintText);\r
+               strbuf.append("\n");\r
+               if (otherConstraintInfo != null)\r
+               {\r
+                       strbuf.append(otherConstraintInfo.toString());\r
+               }\r
+               strbuf.append("\n");\r
+               return strbuf.toString();\r
+       }\r
+}\r