Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
In pg_dump, ensure that view triggers are processed after view rules.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 4 Feb 2016 05:26:10 +0000 (00:26 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 4 Feb 2016 05:26:10 +0000 (00:26 -0500)
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
src/bin/pg_dump/pg_dump.h
src/bin/pg_dump/pg_dump_sort.c

index a553583c34e6c9747f2cf30591a2f66a5de95598..4700e09db42726f160cc532eced0ae6ccd7dfb84 100644 (file)
@@ -5781,6 +5781,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;
index 1e2a00d7a2c36f2d47a558e9880ffda7d1282e72..7d589e6cc56062a73638a5d82c0e3e25eb8bd7c1 100644 (file)
@@ -287,6 +287,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
index b56a8b347e3df09f1d9e33d1a5f9e41926aefa0a..52b89cea283e80fce7dc32c7c5d8fff3a35deecb 100644 (file)
@@ -878,6 +878,7 @@ repairViewRuleMultiLoop(DumpableObject *viewobj,
 {
    TableInfo  *viewinfo = (TableInfo *) viewobj;
    RuleInfo   *ruleinfo = (RuleInfo *) ruleobj;
+   int         i;
 
    /* remove view's dependency on rule */
    removeObjectDependency(viewobj, ruleobj->dumpId);
@@ -895,6 +896,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);
 }
 
 /*