|
6 | 6 | *
|
7 | 7 | *
|
8 | 8 | * 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 $ |
10 | 10 | *
|
11 | 11 | *-------------------------------------------------------------------------
|
12 | 12 | */
|
13 | 13 | #include "postgres.h"
|
14 | 14 |
|
15 | 15 | #include "access/heapam.h"
|
16 | 16 | #include "catalog/pg_shadow.h"
|
| 17 | +#include "optimizer/clauses.h" |
17 | 18 | #include "rewrite/locks.h"
|
18 | 19 | #include "utils/acl.h"
|
19 | 20 | #include "utils/builtins.h"
|
|
22 | 23 |
|
23 | 24 |
|
24 | 25 | /*
|
25 |
| - * ThisLockWasTriggered |
| 26 | + * thisLockWasTriggered |
26 | 27 | *
|
27 | 28 | * walk the tree, if there we find a varnode,
|
28 | 29 | * we check the varattno against the attnum
|
29 | 30 | * if we find at least one such match, we return true
|
30 | 31 | * otherwise, we return false
|
| 32 | + * |
| 33 | + * XXX this should be unified with attribute_used() |
31 | 34 | */
|
| 35 | + |
| 36 | +typedef struct { |
| 37 | + int varno; |
| 38 | + int attnum; |
| 39 | + int sublevels_up; |
| 40 | +} thisLockWasTriggered_context; |
| 41 | + |
32 | 42 | static bool
|
33 |
| -nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum, |
34 |
| - int sublevels_up) |
| 43 | +thisLockWasTriggered_walker (Node *node, |
| 44 | + thisLockWasTriggered_context *context) |
35 | 45 | {
|
36 | 46 | if (node == NULL)
|
37 |
| - return FALSE; |
38 |
| - switch (nodeTag(node)) |
| 47 | + return false; |
| 48 | + if (IsA(node, Var)) |
39 | 49 | {
|
40 |
| - case T_Var: |
41 |
| - { |
42 |
| - Var *var = (Var *) node; |
| 50 | + Var *var = (Var *) node; |
43 | 51 |
|
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; |
90 | 65 |
|
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; |
97 | 89 | }
|
98 |
| - return FALSE; |
| 90 | + return expression_tree_walker(node, thisLockWasTriggered_walker, |
| 91 | + (void *) context); |
99 | 92 | }
|
100 | 93 |
|
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 |
| - */ |
107 | 94 | static bool
|
108 | 95 | thisLockWasTriggered(int varno,
|
109 |
| - AttrNumber attnum, |
| 96 | + int attnum, |
110 | 97 | Query *parsetree)
|
111 | 98 | {
|
| 99 | + thisLockWasTriggered_context context; |
112 | 100 |
|
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; |
120 | 104 |
|
| 105 | + return thisLockWasTriggered_walker((Node *) parsetree, &context); |
121 | 106 | }
|
122 | 107 |
|
123 | 108 | /*
|
|
0 commit comments