From 0ed707e9b7e90891d0eda91b353edf3a69c4b7c4 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 4 Feb 2016 00:26:10 -0500 Subject: [PATCH] In pg_dump, ensure that view triggers are processed after view rules. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a view is split into CREATE TABLE + CREATE RULE to break a circular dependency, then any triggers on the view must be dumped/reloaded after the CREATE RULE; else the backend may reject the CREATE TRIGGER because it's the wrong type of trigger for a plain table. This works all right in plain dump/restore because of pg_dump's sorting heuristic that places triggers after rules. However, when using parallel restore, the ordering must be enforced by a dependency --- and we didn't have one. Fixing this is a mere matter of adding an addObjectDependency() call, except that we need to be able to find all the triggers belonging to the view relation, and there was no easy way to do that. Add fields to pg_dump's TableInfo struct to remember where the associated TriggerInfo struct(s) are. Per bug report from Dennis Kögel. The failure can be exhibited at least as far back as 9.1, so back-patch to all supported branches. --- src/bin/pg_dump/pg_dump.c | 3 +++ src/bin/pg_dump/pg_dump.h | 2 ++ src/bin/pg_dump/pg_dump_sort.c | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index aa01d6a66c..64c2673f9a 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -6261,6 +6261,9 @@ getTriggers(Archive *fout, TableInfo tblinfo[], int numTables) tginfo = (TriggerInfo *) pg_malloc(ntups * sizeof(TriggerInfo)); + tbinfo->numTriggers = ntups; + tbinfo->triggers = tginfo; + for (j = 0; j < ntups; j++) { tginfo[j].dobj.objType = DO_TRIGGER; diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 78b2584ce6..9a1d8f863c 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -257,6 +257,8 @@ typedef struct _tableInfo int numParents; /* number of (immediate) parent tables */ struct _tableInfo **parents; /* TableInfos of immediate parents */ struct _tableDataInfo *dataObj; /* TableDataInfo, if dumping its data */ + int numTriggers; /* number of triggers for table */ + struct _triggerInfo *triggers; /* array of TriggerInfo structs */ } TableInfo; typedef struct _attrDefInfo diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c index b0f6ace9a4..78ff59c342 100644 --- a/src/bin/pg_dump/pg_dump_sort.c +++ b/src/bin/pg_dump/pg_dump_sort.c @@ -884,6 +884,7 @@ repairViewRuleMultiLoop(DumpableObject *viewobj, { TableInfo *viewinfo = (TableInfo *) viewobj; RuleInfo *ruleinfo = (RuleInfo *) ruleobj; + int i; /* remove view's dependency on rule */ removeObjectDependency(viewobj, ruleobj->dumpId); @@ -901,6 +902,9 @@ repairViewRuleMultiLoop(DumpableObject *viewobj, addObjectDependency(ruleobj, viewobj->dumpId); /* now that rule is separate, it must be post-data */ addObjectDependency(ruleobj, postDataBoundId); + /* also, any triggers on the view must be dumped after the rule */ + for (i = 0; i < viewinfo->numTriggers; i++) + addObjectDependency(&(viewinfo->triggers[i].dobj), ruleobj->dumpId); } /*