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, @@ -649,6 +650,29 @@ repairViewRuleLoop(DumpableObject *viewobj, removeObjectDependency(ruleobj, viewobj->dumpId); } +/* + * 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 @@ -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 &&