Clean up rewriter routines to use expression_tree_walker and

expression_tree_mutator rather than ad-hoc tree walking code.  This shortens
the code materially and fixes a fair number of sins of omission.  Also,
change modifyAggrefQual to *not* recurse into subselects, since its mission
is satisfied if it removes aggregate functions from the top level of a
WHERE clause.  This cures problems with queries of the form SELECT ...
WHERE x IN (SELECT ... HAVING something-using-an-aggregate), which would
formerly get mucked up by modifyAggrefQual.  The routine is still
fundamentally broken, of course, but I don't think there's any way to get
rid of it before we implement subselects in FROM ...
This commit is contained in:
Tom Lane 1999-10-01 04:08:24 +00:00
parent ce1f5ed547
commit 389af07cf0
4 changed files with 1003 additions and 2481 deletions

View File

@ -6,7 +6,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.22 1999/09/18 19:07:18 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.23 1999/10/01 04:08:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -14,6 +14,7 @@
#include "access/heapam.h"
#include "catalog/pg_shadow.h"
#include "optimizer/clauses.h"
#include "rewrite/locks.h"
#include "utils/acl.h"
#include "utils/builtins.h"
@ -22,102 +23,86 @@
/*
* ThisLockWasTriggered
* thisLockWasTriggered
*
* walk the tree, if there we find a varnode,
* we check the varattno against the attnum
* if we find at least one such match, we return true
* otherwise, we return false
*
* XXX this should be unified with attribute_used()
*/
typedef struct {
int varno;
int attnum;
int sublevels_up;
} thisLockWasTriggered_context;
static bool
nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum,
int sublevels_up)
thisLockWasTriggered_walker (Node *node,
thisLockWasTriggered_context *context)
{
if (node == NULL)
return FALSE;
switch (nodeTag(node))
return false;
if (IsA(node, Var))
{
case T_Var:
{
Var *var = (Var *) node;
Var *var = (Var *) node;
if (varno == var->varno &&
(attnum == var->varattno || attnum == -1))
return TRUE;
}
break;
case T_Expr:
{
Expr *expr = (Expr *) node;
return nodeThisLockWasTriggered((Node *) expr->args, varno,
attnum, sublevels_up);
}
break;
case T_TargetEntry:
{
TargetEntry *tle = (TargetEntry *) node;
return nodeThisLockWasTriggered(tle->expr, varno, attnum,
sublevels_up);
}
break;
case T_Aggref:
{
Aggref *aggref = (Aggref *) node;
return nodeThisLockWasTriggered(aggref->target, varno, attnum,
sublevels_up);
}
break;
case T_List:
{
List *l;
foreach(l, (List *) node)
{
if (nodeThisLockWasTriggered(lfirst(l), varno, attnum,
sublevels_up))
return TRUE;
}
return FALSE;
}
break;
case T_SubLink:
{
SubLink *sublink = (SubLink *) node;
Query *query = (Query *) sublink->subselect;
return nodeThisLockWasTriggered(query->qual, varno, attnum,
sublevels_up + 1);
}
break;
default:
break;
if (var->varlevelsup == context->sublevels_up &&
var->varno == context->varno &&
(var->varattno == context->attnum || context->attnum == -1))
return true;
return false;
}
return FALSE;
if (IsA(node, SubLink))
{
/*
* Standard expression_tree_walker will not recurse into subselect,
* but here we must do so.
*/
SubLink *sub = (SubLink *) node;
if (thisLockWasTriggered_walker((Node *) (sub->lefthand), context))
return true;
context->sublevels_up++;
if (thisLockWasTriggered_walker((Node *) (sub->subselect), context))
{
context->sublevels_up--; /* not really necessary */
return true;
}
context->sublevels_up--;
return false;
}
if (IsA(node, Query))
{
/* Reach here after recursing down into subselect above... */
Query *qry = (Query *) node;
if (thisLockWasTriggered_walker((Node *) (qry->targetList), context))
return true;
if (thisLockWasTriggered_walker((Node *) (qry->qual), context))
return true;
if (thisLockWasTriggered_walker((Node *) (qry->havingQual), context))
return true;
return false;
}
return expression_tree_walker(node, thisLockWasTriggered_walker,
(void *) context);
}
/*
* thisLockWasTriggered -
* walk the tree, if there we find a varnode, we check the varattno
* against the attnum if we find at least one such match, we return true
* otherwise, we return false
*/
static bool
thisLockWasTriggered(int varno,
AttrNumber attnum,
int attnum,
Query *parsetree)
{
thisLockWasTriggered_context context;
if (nodeThisLockWasTriggered(parsetree->qual, varno, attnum, 0))
return true;
if (nodeThisLockWasTriggered((Node *) parsetree->targetList, varno, attnum, 0))
return true;
return false;
context.varno = varno;
context.attnum = attnum;
context.sublevels_up = 0;
return thisLockWasTriggered_walker((Node *) parsetree, &context);
}
/*

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: rewriteManip.h,v 1.17 1999/07/15 15:21:30 momjian Exp $
* $Id: rewriteManip.h,v 1.18 1999/10/01 04:08:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -16,19 +16,18 @@
#include "rewrite/rewriteHandler.h"
/* RewriteManip.c */
void OffsetVarNodes(Node *node, int offset, int sublevels_up);
void ChangeVarNodes(Node *node, int old_varno, int new_varno,
int sublevels_up);
void AddQual(Query *parsetree, Node *qual);
void AddHavingQual(Query *parsetree, Node *havingQual);
extern void OffsetVarNodes(Node *node, int offset, int sublevels_up);
extern void ChangeVarNodes(Node *node, int old_varno, int new_varno,
int sublevels_up);
extern void AddQual(Query *parsetree, Node *qual);
extern void AddHavingQual(Query *parsetree, Node *havingQual);
extern void AddNotQual(Query *parsetree, Node *qual);
extern void AddGroupClause(Query *parsetree, List *group_by, List *tlist);
void AddNotQual(Query *parsetree, Node *qual);
void AddGroupClause(Query *parsetree, List *group_by, List *tlist);
extern void FixNew(RewriteInfo *info, Query *parsetree);
void FixNew(RewriteInfo *info, Query *parsetree);
void HandleRIRAttributeRule(Query *parsetree, List *rtable, List *targetlist,
int rt_index, int attr_num, int *modified,
int *badpostquel);
extern void HandleRIRAttributeRule(Query *parsetree, List *rtable,
List *targetlist, int rt_index,
int attr_num, int *modified, int *badsql);
#endif /* REWRITEMANIP_H */