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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy