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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy