aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2004-12-14 22:16:32 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2004-12-14 22:16:32 +0000
commit86a069bbed9264daaa85270ece0a2d5959017336 (patch)
treee74e879b34aecd5e4df8cc870ad464fdfccf331a /src
parent94e467061e7e2810cd7f566d837e6bb77edaf10d (diff)
downloadpostgresql-86a069bbed9264daaa85270ece0a2d5959017336.tar.gz
postgresql-86a069bbed9264daaa85270ece0a2d5959017336.zip
Cope with circularities involving a view's ON SELECT rule. I originally
thought there couldn't be any, but the folly of this was exposed by an example from andrew@supernews.com 5-Dec-2004. The patch applies the identical logic already used for table constraints and defaults to ON SELECT rules, so I have reasonable confidence in it even though it might look like complicated logic.
Diffstat (limited to 'src')
-rw-r--r--src/bin/pg_dump/pg_dump.c17
-rw-r--r--src/bin/pg_dump/pg_dump.h4
-rw-r--r--src/bin/pg_dump/pg_dump_sort.c56
3 files changed, 68 insertions, 9 deletions
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index c161b3d0afe..4b96613a1cc 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -12,7 +12,7 @@
* by PostgreSQL
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.395 2004/12/14 21:35:20 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.396 2004/12/14 22:16:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -3160,12 +3160,21 @@ getRules(int *numRules)
*/
if (ruleinfo[i].ruletable->relkind == RELKIND_VIEW &&
ruleinfo[i].ev_type == '1' && ruleinfo[i].is_instead)
+ {
addObjectDependency(&ruleinfo[i].ruletable->dobj,
ruleinfo[i].dobj.dumpId);
+ /* We'll merge the rule into CREATE VIEW, if possible */
+ ruleinfo[i].separate = false;
+ }
else
+ {
addObjectDependency(&ruleinfo[i].dobj,
ruleinfo[i].ruletable->dobj.dumpId);
+ ruleinfo[i].separate = true;
+ }
}
+ else
+ ruleinfo[i].separate = true;
}
PQclear(res);
@@ -7617,10 +7626,10 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
return;
/*
- * If it is an ON SELECT rule, we do not need to dump it because it
- * will be handled via CREATE VIEW for the table.
+ * If it is an ON SELECT rule that is created implicitly by CREATE VIEW,
+ * we do not want to dump it as a separate object.
*/
- if (rinfo->ev_type == '1' && rinfo->is_instead)
+ if (!rinfo->separate)
return;
/*
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 07798c90f47..a6a010d187a 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.113 2004/11/05 19:16:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.114 2004/12/14 22:16:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -252,6 +252,8 @@ typedef struct _ruleInfo
TableInfo *ruletable; /* link to table the rule is for */
char ev_type;
bool is_instead;
+ bool separate; /* TRUE if must dump as separate item */
+ /* separate is always true for non-ON SELECT rules */
} RuleInfo;
typedef struct _triggerInfo
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index 79696f452f7..34b4b468b1f 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump_sort.c,v 1.6 2004/08/29 05:06:53 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump_sort.c,v 1.7 2004/12/14 22:16:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -639,7 +639,8 @@ repairTypeFuncLoop(DumpableObject *typeobj, DumpableObject *funcobj)
/*
* Because we force a view to depend on its ON SELECT rule, while there
* will be an implicit dependency in the other direction, we need to break
- * the loop. We can always do this by removing the implicit dependency.
+ * the loop. If there are no other objects in the loop then we can remove
+ * the implicit dependency and leave the ON SELECT rule non-separate.
*/
static void
repairViewRuleLoop(DumpableObject *viewobj,
@@ -650,6 +651,29 @@ repairViewRuleLoop(DumpableObject *viewobj,
}
/*
+ * However, if there are other objects in the loop, we must break the loop
+ * by making the ON SELECT rule a separately-dumped object.
+ *
+ * Because findLoop() finds shorter cycles before longer ones, it's likely
+ * that we will have previously fired repairViewRuleLoop() and removed the
+ * rule's dependency on the view. Put it back to ensure the rule won't be
+ * emitted before the view...
+ */
+static void
+repairViewRuleMultiLoop(DumpableObject *viewobj,
+ DumpableObject *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 */
+ /* mark rule as needing its own dump */
+ ((RuleInfo *) ruleobj)->separate = true;
+ /* put back rule's dependency on view */
+ addObjectDependency(ruleobj, viewobj->dumpId);
+}
+
+/*
* Because we make tables depend on their CHECK constraints, while there
* will be an automatic dependency in the other direction, we need to break
* the loop. If there are no other objects in the loop then we can remove
@@ -765,7 +789,8 @@ repairDependencyLoop(DumpableObject **loop,
loop[0]->objType == DO_TABLE &&
loop[1]->objType == DO_RULE &&
((RuleInfo *) loop[1])->ev_type == '1' &&
- ((RuleInfo *) loop[1])->is_instead)
+ ((RuleInfo *) loop[1])->is_instead &&
+ ((RuleInfo *) loop[1])->ruletable == (TableInfo *) loop[0])
{
repairViewRuleLoop(loop[0], loop[1]);
return;
@@ -774,12 +799,35 @@ repairDependencyLoop(DumpableObject **loop,
loop[1]->objType == DO_TABLE &&
loop[0]->objType == DO_RULE &&
((RuleInfo *) loop[0])->ev_type == '1' &&
- ((RuleInfo *) loop[0])->is_instead)
+ ((RuleInfo *) loop[0])->is_instead &&
+ ((RuleInfo *) loop[0])->ruletable == (TableInfo *) loop[1])
{
repairViewRuleLoop(loop[1], loop[0]);
return;
}
+ /* Indirect loop involving view and ON SELECT rule */
+ if (nLoop > 2)
+ {
+ for (i = 0; i < nLoop; i++)
+ {
+ if (loop[i]->objType == DO_TABLE)
+ {
+ for (j = 0; j < nLoop; j++)
+ {
+ if (loop[j]->objType == DO_RULE &&
+ ((RuleInfo *) loop[j])->ev_type == '1' &&
+ ((RuleInfo *) loop[j])->is_instead &&
+ ((RuleInfo *) loop[j])->ruletable == (TableInfo *) loop[i])
+ {
+ repairViewRuleMultiLoop(loop[i], loop[j]);
+ return;
+ }
+ }
+ }
+ }
+ }
+
/* Table and CHECK constraint */
if (nLoop == 2 &&
loop[0]->objType == DO_TABLE &&