90beta3_multiplepathconstraint.txt

text/plain

Filename: 90beta3_multiplepathconstraint.txt
Type: text/plain
Part: 0
Message: patch for check constraints using multiple inheritance
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 5f6fe41..d23dcdc 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -96,6 +96,17 @@ typedef struct OnCommitItem
 	SubTransactionId deleting_subid;
 } OnCommitItem;
 
+/*
+ * Visit information needed to prevent redundant constraint merges. This
+ * structure is needed to prevent faulty increments of coninhcount in the case
+ * of a multiple inheritance tree that has multiple paths to a parent.
+ */
+typedef struct ParentVisit
+{
+	Oid   parent;
+	Oid   child;
+} ParentVisit;
+
 static List *on_commits = NIL;
 
 
@@ -300,7 +311,7 @@ static void ATExecAddConstraint(List **wqueue,
 static void ATAddCheckConstraint(List **wqueue,
 					 AlteredTableInfo *tab, Relation rel,
 					 Constraint *constr,
-					 bool recurse, bool recursing);
+					 bool recurse, bool recursing, List *visited);
 static void ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
 						  Constraint *fkconstraint);
 static void ATExecDropConstraint(Relation rel, const char *constrName,
@@ -4584,7 +4595,7 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
 	{
 		case CONSTR_CHECK:
 			ATAddCheckConstraint(wqueue, tab, rel,
-								 newConstraint, recurse, false);
+								 newConstraint, recurse, false, NIL);
 			break;
 
 		case CONSTR_FOREIGN:
@@ -4639,7 +4650,7 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
  */
 static void
 ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
-					 Constraint *constr, bool recurse, bool recursing)
+					 Constraint *constr, bool recurse, bool recursing, List *visited)
 {
 	List	   *newcons;
 	ListCell   *lcon;
@@ -4711,6 +4722,30 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
 		Oid			childrelid = lfirst_oid(child);
 		Relation	childrel;
 		AlteredTableInfo *childtab;
+		ListCell   *lv;
+		bool        skip = false;
+		ParentVisit *visit;
+
+		/* Skip children that were visited from the same direct parent. */
+		foreach(lv, visited)
+		{
+			visit = lfirst(lv);
+
+			if ((visit->parent == RelationGetRelid(rel)) &&
+				(visit->child == childrelid))
+			{
+				skip = true;
+				break;
+			}
+		}
+
+		if (skip)
+			continue;
+
+		visit = (ParentVisit *) palloc(sizeof(ParentVisit));
+		visit->parent = RelationGetRelid(rel);
+		visit->child = childrelid;
+		visited = lappend(visited, visit);
 
 		/* find_inheritance_children already got lock */
 		childrel = heap_open(childrelid, NoLock);
@@ -4721,7 +4756,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
 
 		/* Recurse to child */
 		ATAddCheckConstraint(wqueue, childtab, childrel,
-							 constr, recurse, true);
+							 constr, recurse, true, visited);
 
 		heap_close(childrel, NoLock);
 	}