mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-09 08:10:09 +08:00
Correct error in rewriter that caused SELECT count(*) FROM view
to give wrong results: it should be looking at inJoinSet not inFromCl. Also, make 'modified' flag be local to ApplyRetrieveRule: we should append a rule's quals to the query iff that particular rule applies, not if we have fired any previously-considered rule for the query!
This commit is contained in:
parent
0156fdf9a5
commit
7c22d2e5f0
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.71 2000/04/12 17:15:32 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.72 2000/04/20 00:31:49 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -704,8 +704,7 @@ ApplyRetrieveRule(Query *parsetree,
|
|||||||
int rt_index,
|
int rt_index,
|
||||||
int relation_level,
|
int relation_level,
|
||||||
Relation relation,
|
Relation relation,
|
||||||
bool relWasInJoinSet,
|
bool relWasInJoinSet)
|
||||||
int *modified)
|
|
||||||
{
|
{
|
||||||
Query *rule_action = NULL;
|
Query *rule_action = NULL;
|
||||||
Node *rule_qual;
|
Node *rule_qual;
|
||||||
@ -714,6 +713,7 @@ ApplyRetrieveRule(Query *parsetree,
|
|||||||
*l;
|
*l;
|
||||||
int nothing,
|
int nothing,
|
||||||
rt_length;
|
rt_length;
|
||||||
|
int modified = false;
|
||||||
int badsql = false;
|
int badsql = false;
|
||||||
|
|
||||||
rule_qual = rule->qual;
|
rule_qual = rule->qual;
|
||||||
@ -809,18 +809,23 @@ ApplyRetrieveRule(Query *parsetree,
|
|||||||
parsetree = (Query *) apply_RIR_view((Node *) parsetree,
|
parsetree = (Query *) apply_RIR_view((Node *) parsetree,
|
||||||
rt_index, rte,
|
rt_index, rte,
|
||||||
rule_action->targetList,
|
rule_action->targetList,
|
||||||
modified, 0);
|
&modified, 0);
|
||||||
rule_action = (Query *) apply_RIR_view((Node *) rule_action,
|
rule_action = (Query *) apply_RIR_view((Node *) rule_action,
|
||||||
rt_index, rte,
|
rt_index, rte,
|
||||||
rule_action->targetList,
|
rule_action->targetList,
|
||||||
modified, 0);
|
&modified, 0);
|
||||||
|
/* always apply quals of relation-level rules, whether we found a
|
||||||
|
* var to substitute or not.
|
||||||
|
*/
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HandleRIRAttributeRule(parsetree, rtable, rule_action->targetList,
|
HandleRIRAttributeRule(parsetree, rtable, rule_action->targetList,
|
||||||
rt_index, rule->attrno, modified, &badsql);
|
rt_index, rule->attrno, &modified, &badsql);
|
||||||
|
/* quals will be inserted only if we found uses of the attribute */
|
||||||
}
|
}
|
||||||
if (*modified && !badsql)
|
if (modified && !badsql)
|
||||||
{
|
{
|
||||||
AddQual(parsetree, rule_action->qual);
|
AddQual(parsetree, rule_action->qual);
|
||||||
AddGroupClause(parsetree, rule_action->groupClause,
|
AddGroupClause(parsetree, rule_action->groupClause,
|
||||||
@ -894,7 +899,6 @@ fireRIRrules(Query *parsetree)
|
|||||||
RewriteRule *rule;
|
RewriteRule *rule;
|
||||||
RewriteRule RIRonly;
|
RewriteRule RIRonly;
|
||||||
bool relWasInJoinSet;
|
bool relWasInJoinSet;
|
||||||
int modified = false;
|
|
||||||
int i;
|
int i;
|
||||||
List *l;
|
List *l;
|
||||||
|
|
||||||
@ -910,18 +914,15 @@ fireRIRrules(Query *parsetree)
|
|||||||
rte = rt_fetch(rt_index, parsetree->rtable);
|
rte = rt_fetch(rt_index, parsetree->rtable);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the table is not one named in the original FROM clause then
|
* If the table is not referenced in the query, then we ignore it.
|
||||||
* it must be referenced in the query, or we ignore it. This
|
* This prevents infinite expansion loop due to new rtable entries
|
||||||
* prevents infinite expansion loop due to new rtable entries
|
* inserted by expansion of a rule. A table is referenced if it is
|
||||||
* inserted by expansion of a rule.
|
* part of the join set (a source table), or is the result table,
|
||||||
|
* or is referenced by any Var nodes.
|
||||||
*/
|
*/
|
||||||
if (!rte->inFromCl && rt_index != parsetree->resultRelation &&
|
if (!rte->inJoinSet && rt_index != parsetree->resultRelation &&
|
||||||
!rangeTableEntry_used((Node *) parsetree, rt_index, 0))
|
!rangeTableEntry_used((Node *) parsetree, rt_index, 0))
|
||||||
{
|
|
||||||
/* Make sure the planner ignores it too... */
|
|
||||||
rte->inJoinSet = false;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
rel = heap_openr(rte->relname, AccessShareLock);
|
rel = heap_openr(rte->relname, AccessShareLock);
|
||||||
rules = rel->rd_rules;
|
rules = rel->rd_rules;
|
||||||
@ -989,8 +990,7 @@ fireRIRrules(Query *parsetree)
|
|||||||
rt_index,
|
rt_index,
|
||||||
RIRonly.attrno == -1,
|
RIRonly.attrno == -1,
|
||||||
rel,
|
rel,
|
||||||
relWasInJoinSet,
|
relWasInJoinSet);
|
||||||
&modified);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_close(rel, AccessShareLock);
|
heap_close(rel, AccessShareLock);
|
||||||
|
Loading…
Reference in New Issue
Block a user