Skip to content

Commit 86a069b

Browse files
committed
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.
1 parent 94e4670 commit 86a069b

File tree

3 files changed

+68
-9
lines changed

3 files changed

+68
-9
lines changed

src/bin/pg_dump/pg_dump.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* by PostgreSQL
1313
*
1414
* IDENTIFICATION
15-
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.395 2004/12/14 21:35:20 tgl Exp $
15+
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.396 2004/12/14 22:16:32 tgl Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -3160,12 +3160,21 @@ getRules(int *numRules)
31603160
*/
31613161
if (ruleinfo[i].ruletable->relkind == RELKIND_VIEW &&
31623162
ruleinfo[i].ev_type == '1' && ruleinfo[i].is_instead)
3163+
{
31633164
addObjectDependency(&ruleinfo[i].ruletable->dobj,
31643165
ruleinfo[i].dobj.dumpId);
3166+
/* We'll merge the rule into CREATE VIEW, if possible */
3167+
ruleinfo[i].separate = false;
3168+
}
31653169
else
3170+
{
31663171
addObjectDependency(&ruleinfo[i].dobj,
31673172
ruleinfo[i].ruletable->dobj.dumpId);
3173+
ruleinfo[i].separate = true;
3174+
}
31683175
}
3176+
else
3177+
ruleinfo[i].separate = true;
31693178
}
31703179

31713180
PQclear(res);
@@ -7617,10 +7626,10 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
76177626
return;
76187627

76197628
/*
7620-
* If it is an ON SELECT rule, we do not need to dump it because it
7621-
* will be handled via CREATE VIEW for the table.
7629+
* If it is an ON SELECT rule that is created implicitly by CREATE VIEW,
7630+
* we do not want to dump it as a separate object.
76227631
*/
7623-
if (rinfo->ev_type == '1' && rinfo->is_instead)
7632+
if (!rinfo->separate)
76247633
return;
76257634

76267635
/*

src/bin/pg_dump/pg_dump.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.113 2004/11/05 19:16:19 tgl Exp $
9+
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.114 2004/12/14 22:16:32 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -252,6 +252,8 @@ typedef struct _ruleInfo
252252
TableInfo *ruletable; /* link to table the rule is for */
253253
char ev_type;
254254
bool is_instead;
255+
bool separate; /* TRUE if must dump as separate item */
256+
/* separate is always true for non-ON SELECT rules */
255257
} RuleInfo;
256258

257259
typedef struct _triggerInfo

src/bin/pg_dump/pg_dump_sort.c

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump_sort.c,v 1.6 2004/08/29 05:06:53 momjian Exp $
12+
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump_sort.c,v 1.7 2004/12/14 22:16:32 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -639,7 +639,8 @@ repairTypeFuncLoop(DumpableObject *typeobj, DumpableObject *funcobj)
639639
/*
640640
* Because we force a view to depend on its ON SELECT rule, while there
641641
* will be an implicit dependency in the other direction, we need to break
642-
* the loop. We can always do this by removing the implicit dependency.
642+
* the loop. If there are no other objects in the loop then we can remove
643+
* the implicit dependency and leave the ON SELECT rule non-separate.
643644
*/
644645
static void
645646
repairViewRuleLoop(DumpableObject *viewobj,
@@ -649,6 +650,29 @@ repairViewRuleLoop(DumpableObject *viewobj,
649650
removeObjectDependency(ruleobj, viewobj->dumpId);
650651
}
651652

653+
/*
654+
* However, if there are other objects in the loop, we must break the loop
655+
* by making the ON SELECT rule a separately-dumped object.
656+
*
657+
* Because findLoop() finds shorter cycles before longer ones, it's likely
658+
* that we will have previously fired repairViewRuleLoop() and removed the
659+
* rule's dependency on the view. Put it back to ensure the rule won't be
660+
* emitted before the view...
661+
*/
662+
static void
663+
repairViewRuleMultiLoop(DumpableObject *viewobj,
664+
DumpableObject *ruleobj)
665+
{
666+
/* remove view's dependency on rule */
667+
removeObjectDependency(viewobj, ruleobj->dumpId);
668+
/* pretend view is a plain table and dump it that way */
669+
((TableInfo *) viewobj)->relkind = 'r'; /* RELKIND_RELATION */
670+
/* mark rule as needing its own dump */
671+
((RuleInfo *) ruleobj)->separate = true;
672+
/* put back rule's dependency on view */
673+
addObjectDependency(ruleobj, viewobj->dumpId);
674+
}
675+
652676
/*
653677
* Because we make tables depend on their CHECK constraints, while there
654678
* will be an automatic dependency in the other direction, we need to break
@@ -765,7 +789,8 @@ repairDependencyLoop(DumpableObject **loop,
765789
loop[0]->objType == DO_TABLE &&
766790
loop[1]->objType == DO_RULE &&
767791
((RuleInfo *) loop[1])->ev_type == '1' &&
768-
((RuleInfo *) loop[1])->is_instead)
792+
((RuleInfo *) loop[1])->is_instead &&
793+
((RuleInfo *) loop[1])->ruletable == (TableInfo *) loop[0])
769794
{
770795
repairViewRuleLoop(loop[0], loop[1]);
771796
return;
@@ -774,12 +799,35 @@ repairDependencyLoop(DumpableObject **loop,
774799
loop[1]->objType == DO_TABLE &&
775800
loop[0]->objType == DO_RULE &&
776801
((RuleInfo *) loop[0])->ev_type == '1' &&
777-
((RuleInfo *) loop[0])->is_instead)
802+
((RuleInfo *) loop[0])->is_instead &&
803+
((RuleInfo *) loop[0])->ruletable == (TableInfo *) loop[1])
778804
{
779805
repairViewRuleLoop(loop[1], loop[0]);
780806
return;
781807
}
782808

809+
/* Indirect loop involving view and ON SELECT rule */
810+
if (nLoop > 2)
811+
{
812+
for (i = 0; i < nLoop; i++)
813+
{
814+
if (loop[i]->objType == DO_TABLE)
815+
{
816+
for (j = 0; j < nLoop; j++)
817+
{
818+
if (loop[j]->objType == DO_RULE &&
819+
((RuleInfo *) loop[j])->ev_type == '1' &&
820+
((RuleInfo *) loop[j])->is_instead &&
821+
((RuleInfo *) loop[j])->ruletable == (TableInfo *) loop[i])
822+
{
823+
repairViewRuleMultiLoop(loop[i], loop[j]);
824+
return;
825+
}
826+
}
827+
}
828+
}
829+
}
830+
783831
/* Table and CHECK constraint */
784832
if (nLoop == 2 &&
785833
loop[0]->objType == DO_TABLE &&

0 commit comments

Comments
 (0)