Skip to content

Commit 389af07

Browse files
committed
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 ...
1 parent ce1f5ed commit 389af07

File tree

4 files changed

+979
-2457
lines changed

4 files changed

+979
-2457
lines changed

src/backend/rewrite/locks.c

Lines changed: 61 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66
*
77
*
88
* IDENTIFICATION
9-
* $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.22 1999/09/18 19:07:18 tgl Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.23 1999/10/01 04:08:24 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
1313
#include "postgres.h"
1414

1515
#include "access/heapam.h"
1616
#include "catalog/pg_shadow.h"
17+
#include "optimizer/clauses.h"
1718
#include "rewrite/locks.h"
1819
#include "utils/acl.h"
1920
#include "utils/builtins.h"
@@ -22,102 +23,86 @@
2223

2324

2425
/*
25-
* ThisLockWasTriggered
26+
* thisLockWasTriggered
2627
*
2728
* walk the tree, if there we find a varnode,
2829
* we check the varattno against the attnum
2930
* if we find at least one such match, we return true
3031
* otherwise, we return false
32+
*
33+
* XXX this should be unified with attribute_used()
3134
*/
35+
36+
typedef struct {
37+
int varno;
38+
int attnum;
39+
int sublevels_up;
40+
} thisLockWasTriggered_context;
41+
3242
static bool
33-
nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum,
34-
int sublevels_up)
43+
thisLockWasTriggered_walker (Node *node,
44+
thisLockWasTriggered_context *context)
3545
{
3646
if (node == NULL)
37-
return FALSE;
38-
switch (nodeTag(node))
47+
return false;
48+
if (IsA(node, Var))
3949
{
40-
case T_Var:
41-
{
42-
Var *var = (Var *) node;
50+
Var *var = (Var *) node;
4351

44-
if (varno == var->varno &&
45-
(attnum == var->varattno || attnum == -1))
46-
return TRUE;
47-
}
48-
break;
49-
case T_Expr:
50-
{
51-
Expr *expr = (Expr *) node;
52-
53-
return nodeThisLockWasTriggered((Node *) expr->args, varno,
54-
attnum, sublevels_up);
55-
}
56-
break;
57-
case T_TargetEntry:
58-
{
59-
TargetEntry *tle = (TargetEntry *) node;
60-
61-
return nodeThisLockWasTriggered(tle->expr, varno, attnum,
62-
sublevels_up);
63-
}
64-
break;
65-
case T_Aggref:
66-
{
67-
Aggref *aggref = (Aggref *) node;
68-
69-
return nodeThisLockWasTriggered(aggref->target, varno, attnum,
70-
sublevels_up);
71-
}
72-
break;
73-
case T_List:
74-
{
75-
List *l;
76-
77-
foreach(l, (List *) node)
78-
{
79-
if (nodeThisLockWasTriggered(lfirst(l), varno, attnum,
80-
sublevels_up))
81-
return TRUE;
82-
}
83-
return FALSE;
84-
}
85-
break;
86-
case T_SubLink:
87-
{
88-
SubLink *sublink = (SubLink *) node;
89-
Query *query = (Query *) sublink->subselect;
52+
if (var->varlevelsup == context->sublevels_up &&
53+
var->varno == context->varno &&
54+
(var->varattno == context->attnum || context->attnum == -1))
55+
return true;
56+
return false;
57+
}
58+
if (IsA(node, SubLink))
59+
{
60+
/*
61+
* Standard expression_tree_walker will not recurse into subselect,
62+
* but here we must do so.
63+
*/
64+
SubLink *sub = (SubLink *) node;
9065

91-
return nodeThisLockWasTriggered(query->qual, varno, attnum,
92-
sublevels_up + 1);
93-
}
94-
break;
95-
default:
96-
break;
66+
if (thisLockWasTriggered_walker((Node *) (sub->lefthand), context))
67+
return true;
68+
context->sublevels_up++;
69+
if (thisLockWasTriggered_walker((Node *) (sub->subselect), context))
70+
{
71+
context->sublevels_up--; /* not really necessary */
72+
return true;
73+
}
74+
context->sublevels_up--;
75+
return false;
76+
}
77+
if (IsA(node, Query))
78+
{
79+
/* Reach here after recursing down into subselect above... */
80+
Query *qry = (Query *) node;
81+
82+
if (thisLockWasTriggered_walker((Node *) (qry->targetList), context))
83+
return true;
84+
if (thisLockWasTriggered_walker((Node *) (qry->qual), context))
85+
return true;
86+
if (thisLockWasTriggered_walker((Node *) (qry->havingQual), context))
87+
return true;
88+
return false;
9789
}
98-
return FALSE;
90+
return expression_tree_walker(node, thisLockWasTriggered_walker,
91+
(void *) context);
9992
}
10093

101-
/*
102-
* thisLockWasTriggered -
103-
* walk the tree, if there we find a varnode, we check the varattno
104-
* against the attnum if we find at least one such match, we return true
105-
* otherwise, we return false
106-
*/
10794
static bool
10895
thisLockWasTriggered(int varno,
109-
AttrNumber attnum,
96+
int attnum,
11097
Query *parsetree)
11198
{
99+
thisLockWasTriggered_context context;
112100

113-
if (nodeThisLockWasTriggered(parsetree->qual, varno, attnum, 0))
114-
return true;
115-
116-
if (nodeThisLockWasTriggered((Node *) parsetree->targetList, varno, attnum, 0))
117-
return true;
118-
119-
return false;
101+
context.varno = varno;
102+
context.attnum = attnum;
103+
context.sublevels_up = 0;
120104

105+
return thisLockWasTriggered_walker((Node *) parsetree, &context);
121106
}
122107

123108
/*

0 commit comments

Comments
 (0)