--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.compile.FKConstraintDefinitionNode\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.types.TypeId;\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;\r
+import org.apache.derby.iapi.sql.conn.Authorizer;\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.impl.sql.compile.ActivationClassBuilder;\r
+import org.apache.derby.impl.sql.execute.ConstraintInfo;\r
+\r
+import org.apache.derby.iapi.util.JBitSet;\r
+import org.apache.derby.iapi.util.ReuseFactory;\r
+import org.apache.derby.iapi.sql.dictionary.DDUtils;\r
+\r
+/**\r
+ * A FKConstraintDefintionNode represents table constraint definitions.\r
+ *\r
+ */\r
+\r
+public final class FKConstraintDefinitionNode extends ConstraintDefinitionNode\r
+{\r
+ TableName refTableName;\r
+ ResultColumnList refRcl;\r
+ SchemaDescriptor refTableSd;\r
+ int refActionDeleteRule; // referential action on delete\r
+ int refActionUpdateRule; // referential action on update\r
+ public void init(\r
+ Object constraintName, \r
+ Object refTableName, \r
+ Object fkRcl,\r
+ Object refRcl,\r
+ Object refActions)\r
+ {\r
+ super.init(\r
+ constraintName,\r
+ ReuseFactory.getInteger(DataDictionary.FOREIGNKEY_CONSTRAINT),\r
+ fkRcl, \r
+ null,\r
+ null,\r
+ null);\r
+ this.refRcl = (ResultColumnList) refRcl;\r
+ this.refTableName = (TableName) refTableName;\r
+\r
+ this.refActionDeleteRule = ((int[]) refActions)[0];\r
+ this.refActionUpdateRule = ((int[]) refActions)[1];\r
+ }\r
+\r
+ /**\r
+ * Bind this constraint definition. Figure out some\r
+ * information about the table we are binding against.\r
+ *\r
+ * @param dd DataDictionary\r
+ * \r
+ * @exception StandardException on error\r
+ */\r
+ protected void bind(DDLStatementNode ddlNode, DataDictionary dd) throws StandardException\r
+ {\r
+ super.bind(ddlNode, dd);\r
+\r
+ refTableSd = getSchemaDescriptor(refTableName.getSchemaName());\r
+\r
+ if (refTableSd.isSystemSchema())\r
+ {\r
+ throw StandardException.newException(SQLState.LANG_NO_FK_ON_SYSTEM_SCHEMA);\r
+ }\r
+\r
+ // check the referenced table, unless this is a self-referencing constraint\r
+ if (refTableName.equals(ddlNode.getObjectName()))\r
+ return;\r
+\r
+ // error when the referenced table does not exist\r
+ TableDescriptor td = getTableDescriptor(refTableName.getTableName(), refTableSd);\r
+ if (td == null)\r
+ throw StandardException.newException(SQLState.LANG_INVALID_FK_NO_REF_TAB, \r
+ getConstraintMoniker(), \r
+ refTableName.getTableName());\r
+\r
+ // Verify if REFERENCES_PRIV is granted to columns referenced\r
+ getCompilerContext().pushCurrentPrivType(getPrivType());\r
+\r
+ // Indicate that this statement has a dependency on the\r
+ // table which is referenced by this foreign key:\r
+ getCompilerContext().createDependency(td);\r
+\r
+ // If references clause doesn't have columnlist, get primary key info\r
+ if (refRcl.size()==0 && (td.getPrimaryKey() != null))\r
+ {\r
+ // Get the primary key columns\r
+ int[] refCols = td.getPrimaryKey().getReferencedColumns();\r
+ for (int i=0; i<refCols.length; i++)\r
+ {\r
+ ColumnDescriptor cd = td.getColumnDescriptor(refCols[i]);\r
+ // Set tableDescriptor for this column descriptor. Needed for adding required table\r
+ // access permission. Column descriptors may not have this set already.\r
+ cd.setTableDescriptor(td);\r
+ if (isPrivilegeCollectionRequired())\r
+ getCompilerContext().addRequiredColumnPriv(cd);\r
+ }\r
+\r
+ }\r
+ else\r
+ {\r
+ for (int i=0; i<refRcl.size(); i++)\r
+ {\r
+ ResultColumn rc = (ResultColumn) refRcl.elementAt(i);\r
+ ColumnDescriptor cd = td.getColumnDescriptor(rc.getName());\r
+ if (cd != null)\r
+ {\r
+ // Set tableDescriptor for this column descriptor. Needed for adding required table\r
+ // access permission. Column descriptors may not have this set already.\r
+ cd.setTableDescriptor(td);\r
+ if (isPrivilegeCollectionRequired())\r
+ getCompilerContext().addRequiredColumnPriv(cd);\r
+ }\r
+ }\r
+ }\r
+ getCompilerContext().popCurrentPrivType();\r
+ }\r
+\r
+ public ConstraintInfo getReferencedConstraintInfo()\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT(refTableSd != null, \r
+ "You must call bind() before calling getConstraintInfo");\r
+ }\r
+ return new ConstraintInfo(refTableName.getTableName(), refTableSd,\r
+ refRcl.getColumnNames(), refActionDeleteRule,\r
+ refActionUpdateRule);\r
+ }\r
+\r
+ public TableName getRefTableName() { return refTableName; }\r
+\r
+ int getPrivType()\r
+ {\r
+ return Authorizer.REFERENCES_PRIV;\r
+ }\r
+}\r