summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2016-02-04 00:26:10 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2016-02-04 00:26:10 -0500
commit9c704632c26976468a83010b18edefc4851fb2dd (patch)
treec30434c3501380fc8f8f4fbf5eee3e572b808df7
parent4c8b07d3c4300dd9e6e3a8b6dc8260c128a9cd75 (diff)
downloadpostgresql-9c704632c26976468a83010b18edefc4851fb2dd.tar.gz
In pg_dump, ensure that view triggers are processed after view rules.
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.
-rw-r--r--src/bin/pg_dump/pg_dump.c3
-rw-r--r--src/bin/pg_dump/pg_dump.h2
-rw-r--r--src/bin/pg_dump/pg_dump_sort.c11
3 files changed, 14 insertions, 2 deletions
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 4f1a5caee4..662d43a579 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -5346,6 +5346,9 @@ getTriggers(TableInfo tblinfo[], int numTables)
tginfo = (TriggerInfo *) 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 0bd291456b..d12680e9f0 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -288,6 +288,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 a9d44897c6..0c5ef4a270 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -756,16 +756,23 @@ static void
repairViewRuleMultiLoop(DumpableObject *viewobj,
DumpableObject *ruleobj)
{
+ TableInfo *viewinfo = (TableInfo *) viewobj;
+ RuleInfo *ruleinfo = (RuleInfo *) ruleobj;
+ int i;
+
/* remove view's dependency on rule */
removeObjectDependency(viewobj, ruleobj->dumpId);
/* pretend view is a plain table and dump it that way */
- ((TableInfo *) viewobj)->relkind = 'r'; /* RELKIND_RELATION */
+ viewinfo->relkind = 'r'; /* RELKIND_RELATION */
/* mark rule as needing its own dump */
- ((RuleInfo *) ruleobj)->separate = true;
+ ruleinfo->separate = true;
/* put back rule's dependency on view */
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);
}
/*