]> granicus.if.org Git - postgresql/commitdiff
Fix dumping of security_barrier views with circular dependencies.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 21 Aug 2012 19:18:36 +0000 (15:18 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 21 Aug 2012 19:19:12 +0000 (15:19 -0400)
If a view has circular dependencies, pg_dump splits it into a CREATE TABLE
and a CREATE RULE command to break the dependency loop.  However, if the
view has reloptions, those options cannot be applied in the CREATE TABLE
command, because views and tables have different allowed reloptions so
CREATE TABLE would reject them.  Instead apply the reloptions after the
CREATE RULE, using ALTER VIEW SET.

src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.h
src/bin/pg_dump/pg_dump_sort.c

index 7d672878ed359bebc4df2f2d1cf357a2f043c64e..dbf589a72b6c8c8997e5f7631b81c160d08cc45c 100644 (file)
@@ -5062,6 +5062,16 @@ getRules(Archive *fout, int *numRules)
                }
                else
                        ruleinfo[i].separate = true;
+
+               /*
+                * If we're forced to break a dependency loop by dumping a view as a
+                * table and separate _RETURN rule, we'll move the view's reloptions
+                * to the rule.  (This is necessary because tables and views have
+                * different valid reloptions, so we can't apply the options until the
+                * backend knows it's a view.)  Otherwise the rule's reloptions stay
+                * NULL.
+                */
+               ruleinfo[i].reloptions = NULL;
        }
 
        PQclear(res);
@@ -13724,10 +13734,7 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
         */
        if (rinfo->ev_enabled != 'O')
        {
-               appendPQExpBuffer(cmd, "ALTER TABLE %s.",
-                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
-               appendPQExpBuffer(cmd, "%s ",
-                                                 fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(cmd, "ALTER TABLE %s ", fmtId(tbinfo->dobj.name));
                switch (rinfo->ev_enabled)
                {
                        case 'A':
@@ -13745,6 +13752,16 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
                }
        }
 
+       /*
+        * Apply view's reloptions when its ON SELECT rule is separate.
+        */
+       if (rinfo->reloptions)
+       {
+               appendPQExpBuffer(cmd, "ALTER VIEW %s SET (%s);\n",
+                                                 fmtId(tbinfo->dobj.name),
+                                                 rinfo->reloptions);
+       }
+
        /*
         * DROP must be fully qualified in case same name appears in pg_catalog
         */
index b44187bbdcfc3a809b32059a00966b09581cd2a3..dad791d5c3e038b9d75796cfc67aec27e9a9735d 100644 (file)
@@ -332,6 +332,8 @@ typedef struct _ruleInfo
        char            ev_enabled;
        bool            separate;               /* TRUE if must dump as separate item */
        /* separate is always true for non-ON SELECT rules */
+       char       *reloptions;         /* options specified by WITH (...) */
+       /* reloptions is only set if we need to dump the options with the rule */
 } RuleInfo;
 
 typedef struct _triggerInfo
index 7e28ed4245f8736a2d1b8096302643f9b999fdaf..d5a952435d5c5cbbf6318e79c71f29cfb2c8f82b 100644 (file)
@@ -722,12 +722,21 @@ static void
 repairViewRuleMultiLoop(DumpableObject *viewobj,
                                                DumpableObject *ruleobj)
 {
+       TableInfo  *viewinfo = (TableInfo *) viewobj;
+       RuleInfo   *ruleinfo = (RuleInfo *) ruleobj;
+
        /* 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;
+       /* move any reloptions from view to rule */
+       if (viewinfo->reloptions)
+       {
+               ruleinfo->reloptions = viewinfo->reloptions;
+               viewinfo->reloptions = NULL;
+       }
        /* put back rule's dependency on view */
        addObjectDependency(ruleobj, viewobj->dumpId);
        /* now that rule is separate, it must be post-data */