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:
Tom Lane 2000-04-20 00:31:49 +00:00
parent 0156fdf9a5
commit 7c22d2e5f0

View File

@ -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);