|
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 | +typedefstruct { |
| 37 | +intvarno; |
| 38 | +intattnum; |
| 39 | +intsublevels_up; |
| 40 | +}thisLockWasTriggered_context; |
| 41 | + |
32 | 42 | staticbool |
33 | | -nodeThisLockWasTriggered(Node*node,intvarno,AttrNumberattnum, |
34 | | -intsublevels_up) |
| 43 | +thisLockWasTriggered_walker(Node*node, |
| 44 | +thisLockWasTriggered_context*context) |
35 | 45 | { |
36 | 46 | if (node==NULL) |
37 | | -returnFALSE; |
38 | | -switch (nodeTag(node)) |
| 47 | +returnfalse; |
| 48 | +if (IsA(node,Var)) |
39 | 49 | { |
40 | | -caseT_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 | | -caseT_Expr: |
50 | | -{ |
51 | | -Expr*expr= (Expr*)node; |
52 | | - |
53 | | -returnnodeThisLockWasTriggered((Node*)expr->args,varno, |
54 | | -attnum,sublevels_up); |
55 | | -} |
56 | | -break; |
57 | | -caseT_TargetEntry: |
58 | | -{ |
59 | | -TargetEntry*tle= (TargetEntry*)node; |
60 | | - |
61 | | -returnnodeThisLockWasTriggered(tle->expr,varno,attnum, |
62 | | -sublevels_up); |
63 | | -} |
64 | | -break; |
65 | | -caseT_Aggref: |
66 | | -{ |
67 | | -Aggref*aggref= (Aggref*)node; |
68 | | - |
69 | | -returnnodeThisLockWasTriggered(aggref->target,varno,attnum, |
70 | | -sublevels_up); |
71 | | -} |
72 | | -break; |
73 | | -caseT_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 | | -caseT_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 | | -returnnodeThisLockWasTriggered(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 | +returnexpression_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 | staticbool |
108 | 95 | thisLockWasTriggered(intvarno, |
109 | | -AttrNumberattnum, |
| 96 | +intattnum, |
110 | 97 | Query*parsetree) |
111 | 98 | { |
| 99 | +thisLockWasTriggered_contextcontext; |
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 | +returnthisLockWasTriggered_walker((Node*)parsetree,&context); |
121 | 106 | } |
122 | 107 |
|
123 | 108 | /* |
|