From dfe3abe20023b94df8004b4e025e9991a83ee264 Mon Sep 17 00:00:00 2001
From: Thomas Mueller <thomasmueller@users.noreply.github.com>
Date: Mon, 20 Oct 2008 20:34:32 +0000
Subject: [PATCH] Self referencing constraints didn't restrict deleting rows
 that reference itself if there is another row that references it.

---
 .../h2/constraint/ConstraintReferential.java  | 28 ++++---------------
 1 file changed, 6 insertions(+), 22 deletions(-)

diff --git a/h2/src/main/org/h2/constraint/ConstraintReferential.java b/h2/src/main/org/h2/constraint/ConstraintReferential.java
index 748d704c0..3a47be219 100644
--- a/h2/src/main/org/h2/constraint/ConstraintReferential.java
+++ b/h2/src/main/org/h2/constraint/ConstraintReferential.java
@@ -343,18 +343,21 @@ public class ConstraintReferential extends Constraint {
             int refIdx = refCol.getColumnId();
             check.setValue(refIdx, v.convertTo(refCol.getType()));
         }
-        if (!found(session, refIndex, check)) {
+        if (!found(session, refIndex, check, null)) {
             throw Message.getSQLException(ErrorCode.REFERENTIAL_INTEGRITY_VIOLATED_PARENT_MISSING_1,
                     getShortDescription());
         }
     }
 
-    private boolean found(Session session, Index index, SearchRow check) throws SQLException {
+    private boolean found(Session session, Index index, SearchRow check, Row excluding) throws SQLException {
         index.getTable().lock(session, false, false);
         Cursor cursor = index.find(session, check, check);
         while (cursor.next()) {
             SearchRow found;
             found = cursor.getSearchRow();
+            if (excluding != null && found.getPos() == excluding.getPos()) {
+                continue;
+            }
             Column[] cols = index.getColumns();
             boolean allEqual = true;
             for (int i = 0; i < columns.length && i < cols.length; i++) {
@@ -378,25 +381,6 @@ public class ConstraintReferential extends Constraint {
     }
 
     private void checkRow(Session session, Row oldRow) throws SQLException {
-        if (refTable == table) {
-            // special case self referencing constraints: check the deleted row
-            // first
-            boolean self = true;
-            for (int i = 0; i < columns.length; i++) {
-                Column refCol = refColumns[i].column;
-                int refIdx = refCol.getColumnId();
-                Value v = oldRow.getValue(refIdx);
-                int idx = columns[i].column.getColumnId();
-                Value r = oldRow.getValue(idx);
-                if (!database.areEqual(r, v)) {
-                    self = false;
-                    break;
-                }
-            }
-            if (self) {
-                return;
-            }
-        }
         SearchRow check = table.getTemplateSimpleRow(false);
         for (int i = 0; i < columns.length; i++) {
             Column refCol = refColumns[i].column;
@@ -406,7 +390,7 @@ public class ConstraintReferential extends Constraint {
             Value v = oldRow.getValue(refIdx).convertTo(col.getType());
             check.setValue(idx, v);
         }
-        if (found(session, index, check)) {
+        if (found(session, index, check, oldRow)) {
             throw Message.getSQLException(ErrorCode.REFERENTIAL_INTEGRITY_VIOLATED_CHILD_EXISTS_1,
                     getShortDescription());
         }
-- 
2.18.1