multiple_inheritance-v3.patch
text/plain
Filename: multiple_inheritance-v3.patch
Type: text/plain
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v3
| File | + | − |
|---|---|---|
| src/backend/commands/tablecmds.c | 43 | 5 |
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 49a6f73..d43efc3 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -99,7 +99,6 @@ typedef struct OnCommitItem
static List *on_commits = NIL;
-
/*
* State information for ALTER TABLE
*
@@ -132,6 +131,7 @@ typedef struct AlteredTableInfo
Oid relid; /* Relation to work on */
char relkind; /* Its relkind */
TupleDesc oldDesc; /* Pre-modification tuple descriptor */
+ bool relVisited; /* Was the rel visited before, for the current subcommand */
/* Information saved by Phase 1 for Phase 2: */
List *subcmds[AT_NUM_PASSES]; /* Lists of AlterTableCmd */
/* Information saved by Phases 1/2 for Phase 3: */
@@ -335,6 +335,7 @@ static void ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
static void copy_relation_data(SMgrRelation rel, SMgrRelation dst,
ForkNumber forkNum, bool istemp);
static const char *storage_name(char c);
+static void ATResetRelVisited(List **wqueue);
/* ----------------------------------------------------------------
@@ -2583,6 +2584,7 @@ ATController(Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
{
AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
+ ATResetRelVisited(&wqueue);
ATPrepCmd(&wqueue, rel, cmd, recurse, false, lockmode);
}
@@ -3503,6 +3505,23 @@ ATGetQueueEntry(List **wqueue, Relation rel)
}
/*
+ * ATResetRelVisited: reset the visitation info for each rel in the working
+ * queue, so it can be used for the next subcommand.
+ */
+static void
+ATResetRelVisited(List **wqueue)
+{
+ AlteredTableInfo *tab;
+ ListCell *ltab;
+
+ foreach(ltab, *wqueue)
+ {
+ tab = (AlteredTableInfo *) lfirst(ltab);
+ tab->relVisited = false;
+ }
+}
+
+/*
* ATSimplePermissions
*
* - Ensure that it is a relation (or possibly a view)
@@ -3618,19 +3637,29 @@ ATSimpleRecursion(List **wqueue, Relation rel,
/*
* ATOneLevelRecursion
*
- * Here, we visit only direct inheritance children. It is expected that
- * the command's prep routine will recurse again to find indirect children.
- * When using this technique, a multiply-inheriting child will be visited
- * multiple times.
+ * Here, we visit only direct inheritance children. It is expected that the
+ * command's prep routine will recurse again to find indirect children. When
+ * using this technique, a multiple-inheriting child will be visited multiple
+ * times. Childs of multiple-inheriting childs however are only visited once
+ * for each parent.
*/
static void
ATOneLevelRecursion(List **wqueue, Relation rel,
AlterTableCmd *cmd, LOCKMODE lockmode)
{
Oid relid = RelationGetRelid(rel);
+ AlteredTableInfo *tab = ATGetQueueEntry(wqueue, rel);
ListCell *child;
List *children;
+ /* If we already visited the current multiple-inheriting relation, we
+ * mustn't recurse to it's child tables, because they've already been
+ * visited. Visiting them would lead to an incorrect value for
+ * attinhcount. */
+ if (tab->relVisited)
+ return;
+ tab->relVisited = true;
+
children = find_inheritance_children(relid, lockmode);
foreach(child, children)
@@ -4891,6 +4920,15 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
CommandCounterIncrement();
/*
+ * If the constraint got merged with an existing constraint, we're done.
+ * We mustn't recurse to child tables in this case, because they've already
+ * got the constraint, and visiting them again would lead to an incorrect
+ * value for coninhcount.
+ */
+ if (newcons == NIL)
+ return;
+
+ /*
* Propagate to children as appropriate. Unlike most other ALTER
* routines, we have to do this one level of recursion at a time; we can't
* use find_all_inheritors to do it in one pass.