90beta3_multiplepathconstraint.txt
text/plain
Filename: 90beta3_multiplepathconstraint.txt
Type: text/plain
Part: 0
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);
}