--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.execute.ReferencedKeyRIChecker\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
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.sql.StatementUtil;\r
+import org.apache.derby.iapi.sql.execute.ExecRow;\r
+import org.apache.derby.iapi.sql.execute.ExecIndexRow;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.store.access.ScanController;\r
+import org.apache.derby.iapi.store.access.TransactionController;\r
+import org.apache.derby.iapi.sql.StatementType;\r
+\r
+/**\r
+ * A Referential Integrity checker for a change\r
+ * to a referenced key (primary or unique). Makes\r
+ * sure that all the referenced key row is not\r
+ * referenced by any of its foreign keys. see \r
+ * ForeignKeyRIChecker for the code that validates\r
+ * changes to foreign keys.\r
+ */\r
+public class ReferencedKeyRIChecker extends GenericRIChecker\r
+{\r
+ /**\r
+ * @param tc the xact controller\r
+ * @param fkinfo the foreign key information \r
+ *\r
+ * @exception StandardException Thrown on failure\r
+ */\r
+ ReferencedKeyRIChecker(TransactionController tc, FKInfo fkinfo)\r
+ throws StandardException\r
+ {\r
+ super(tc, fkinfo);\r
+\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ if (fkInfo.type != FKInfo.REFERENCED_KEY)\r
+ {\r
+ SanityManager.THROWASSERT("invalid type "+fkInfo.type+\r
+ " for a ReferencedKeyRIChecker");\r
+ }\r
+ } \r
+ }\r
+\r
+ /**\r
+ * Check that the row either has a null column(s), or\r
+ * has no corresponding foreign keys.\r
+ * <p> \r
+ * If a foreign key is found, an exception is thrown.\r
+ * If not, the scan is closed.\r
+ *\r
+ * @param row the row to check\r
+ *\r
+ * @exception StandardException on unexpected error, or\r
+ * on a primary/unique key violation\r
+ */\r
+ void doCheck(ExecRow row, boolean restrictCheckOnly) throws StandardException\r
+ {\r
+ /*\r
+ ** If any of the columns are null, then the\r
+ ** check always succeeds.\r
+ */\r
+ if (isAnyFieldNull(row))\r
+ {\r
+ return;\r
+ }\r
+\r
+ /*\r
+ ** Otherwise, should be no rows found.\r
+ ** Check each conglomerate.\r
+ */\r
+ ScanController scan;\r
+\r
+ for (int i = 0; i < fkInfo.fkConglomNumbers.length; i++)\r
+ {\r
+ \r
+ if(restrictCheckOnly)\r
+ {\r
+ if(fkInfo.raRules[i] != StatementType.RA_RESTRICT)\r
+ continue;\r
+ }\r
+\r
+ scan = getScanController(fkInfo.fkConglomNumbers[i], fkScocis[i], fkDcocis[i], row);\r
+ if (scan.next())\r
+ {\r
+ close();\r
+ StandardException se = StandardException.newException(SQLState.LANG_FK_VIOLATION, fkInfo.fkConstraintNames[i],\r
+ fkInfo.tableName,\r
+ StatementUtil.typeName(fkInfo.stmtType),\r
+ RowUtil.toString(row, fkInfo.colArray));\r
+\r
+ throw se;\r
+ }\r
+ /*\r
+ ** Move off of the current row to release any locks.\r
+ */\r
+ scan.next();\r
+ }\r
+ }\r
+}\r
+\r
+\r
+\r
+\r
+\r