mirror of
https://github.com/postgres/postgres.git
synced 2025-04-29 13:56:47 +03:00
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.
This commit is contained in:
parent
94e467061e
commit
86a069bbed
@ -12,7 +12,7 @@
|
|||||||
* by PostgreSQL
|
* by PostgreSQL
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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,13 +3160,22 @@ getRules(int *numRules)
|
|||||||
*/
|
*/
|
||||||
if (ruleinfo[i].ruletable->relkind == RELKIND_VIEW &&
|
if (ruleinfo[i].ruletable->relkind == RELKIND_VIEW &&
|
||||||
ruleinfo[i].ev_type == '1' && ruleinfo[i].is_instead)
|
ruleinfo[i].ev_type == '1' && ruleinfo[i].is_instead)
|
||||||
|
{
|
||||||
addObjectDependency(&ruleinfo[i].ruletable->dobj,
|
addObjectDependency(&ruleinfo[i].ruletable->dobj,
|
||||||
ruleinfo[i].dobj.dumpId);
|
ruleinfo[i].dobj.dumpId);
|
||||||
|
/* We'll merge the rule into CREATE VIEW, if possible */
|
||||||
|
ruleinfo[i].separate = false;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
addObjectDependency(&ruleinfo[i].dobj,
|
addObjectDependency(&ruleinfo[i].dobj,
|
||||||
ruleinfo[i].ruletable->dobj.dumpId);
|
ruleinfo[i].ruletable->dobj.dumpId);
|
||||||
|
ruleinfo[i].separate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ruleinfo[i].separate = true;
|
||||||
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
@ -7617,10 +7626,10 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If it is an ON SELECT rule, we do not need to dump it because it
|
* If it is an ON SELECT rule that is created implicitly by CREATE VIEW,
|
||||||
* will be handled via CREATE VIEW for the table.
|
* we do not want to dump it as a separate object.
|
||||||
*/
|
*/
|
||||||
if (rinfo->ev_type == '1' && rinfo->is_instead)
|
if (!rinfo->separate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 */
|
TableInfo *ruletable; /* link to table the rule is for */
|
||||||
char ev_type;
|
char ev_type;
|
||||||
bool is_instead;
|
bool is_instead;
|
||||||
|
bool separate; /* TRUE if must dump as separate item */
|
||||||
|
/* separate is always true for non-ON SELECT rules */
|
||||||
} RuleInfo;
|
} RuleInfo;
|
||||||
|
|
||||||
typedef struct _triggerInfo
|
typedef struct _triggerInfo
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* 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
|
* 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
|
static void
|
||||||
repairViewRuleLoop(DumpableObject *viewobj,
|
repairViewRuleLoop(DumpableObject *viewobj,
|
||||||
@ -649,6 +650,29 @@ repairViewRuleLoop(DumpableObject *viewobj,
|
|||||||
removeObjectDependency(ruleobj, viewobj->dumpId);
|
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
|
* Because we make tables depend on their CHECK constraints, while there
|
||||||
* will be an automatic dependency in the other direction, we need to break
|
* 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[0]->objType == DO_TABLE &&
|
||||||
loop[1]->objType == DO_RULE &&
|
loop[1]->objType == DO_RULE &&
|
||||||
((RuleInfo *) loop[1])->ev_type == '1' &&
|
((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]);
|
repairViewRuleLoop(loop[0], loop[1]);
|
||||||
return;
|
return;
|
||||||
@ -774,12 +799,35 @@ repairDependencyLoop(DumpableObject **loop,
|
|||||||
loop[1]->objType == DO_TABLE &&
|
loop[1]->objType == DO_TABLE &&
|
||||||
loop[0]->objType == DO_RULE &&
|
loop[0]->objType == DO_RULE &&
|
||||||
((RuleInfo *) loop[0])->ev_type == '1' &&
|
((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]);
|
repairViewRuleLoop(loop[1], loop[0]);
|
||||||
return;
|
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 */
|
/* Table and CHECK constraint */
|
||||||
if (nLoop == 2 &&
|
if (nLoop == 2 &&
|
||||||
loop[0]->objType == DO_TABLE &&
|
loop[0]->objType == DO_TABLE &&
|
||||||
|
Loading…
x
Reference in New Issue
Block a user