|
7 | 7 | *
|
8 | 8 | *
|
9 | 9 | * IDENTIFICATION
|
10 |
| - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.88 2001/01/24 19:43:05 momjian Exp $ |
| 10 | + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.89 2001/01/27 04:40:59 tgl Exp $ |
11 | 11 | *
|
12 | 12 | *-------------------------------------------------------------------------
|
13 | 13 | */
|
@@ -37,7 +37,7 @@ static RewriteInfo *gatherRewriteMeta(Query *parsetree,
|
37 | 37 | int rt_index,
|
38 | 38 | CmdType event,
|
39 | 39 | bool instead_flag);
|
40 |
| -static List *adjustJoinTreeList(Query *parsetree, int rt_index, bool *found); |
| 40 | +static List *adjustJoinTreeList(Query *parsetree, bool removert, int rt_index); |
41 | 41 | static void markQueryForUpdate(Query *qry, bool skipOldNew);
|
42 | 42 | static List *matchLocks(CmdType event, RuleLock *rulelocks,
|
43 | 43 | int varno, Query *parsetree);
|
@@ -119,18 +119,25 @@ gatherRewriteMeta(Query *parsetree,
|
119 | 119 |
|
120 | 120 | /*
|
121 | 121 | * Each rule action's jointree should be the main parsetree's jointree
|
122 |
| - * plus that rule's jointree, but *without* the original rtindex |
| 122 | + * plus that rule's jointree, but usually *without* the original rtindex |
123 | 123 | * that we're replacing (if present, which it won't be for INSERT).
|
124 |
| - * Note that if the rule refers to OLD, its jointree will add back |
125 |
| - * a reference to rt_index. |
| 124 | + * Note that if the rule action refers to OLD, its jointree will add |
| 125 | + * a reference to rt_index. If the rule action doesn't refer to OLD, |
| 126 | + * but either the rule_qual or the user query quals do, then we need to |
| 127 | + * keep the original rtindex in the jointree to provide data for the |
| 128 | + * quals. We don't want the original rtindex to be joined twice, |
| 129 | + * however, so avoid keeping it if the rule action mentions it. |
126 | 130 | */
|
127 | 131 | if (sub_action->jointree != NULL)
|
128 | 132 | {
|
129 |
| - bool found; |
130 |
| - List *newjointree = adjustJoinTreeList(parsetree, |
131 |
| - rt_index, |
132 |
| - &found); |
133 |
| - |
| 133 | + bool keeporig; |
| 134 | + List *newjointree; |
| 135 | + |
| 136 | + keeporig = (! rangeTableEntry_used((Node *) sub_action->jointree, |
| 137 | + rt_index, 0)) && |
| 138 | + (rangeTableEntry_used(info->rule_qual, rt_index, 0) || |
| 139 | + rangeTableEntry_used(parsetree->jointree->quals, rt_index, 0)); |
| 140 | + newjointree = adjustJoinTreeList(parsetree, !keeporig, rt_index); |
134 | 141 | sub_action->jointree->fromlist =
|
135 | 142 | nconc(newjointree, sub_action->jointree->fromlist);
|
136 | 143 | }
|
@@ -181,29 +188,30 @@ gatherRewriteMeta(Query *parsetree,
|
181 | 188 | }
|
182 | 189 |
|
183 | 190 | /*
|
184 |
| - * Copy the query's jointree list, and attempt to remove any occurrence |
185 |
| - * of the given rt_index as a top-level join item (we do not look for it |
186 |
| - * within join items; this is OK because we are only expecting to find it |
187 |
| - * as an UPDATE or DELETE target relation, which will be at the top level |
188 |
| - * of the join). Returns modified jointree list --- original list |
189 |
| - * is not changed. *found is set to indicate if we found the rt_index. |
| 191 | + * Copy the query's jointree list, and optionally attempt to remove any |
| 192 | + * occurrence of the given rt_index as a top-level join item (we do not look |
| 193 | + * for it within join items; this is OK because we are only expecting to find |
| 194 | + * it as an UPDATE or DELETE target relation, which will be at the top level |
| 195 | + * of the join). Returns modified jointree list --- original list is not |
| 196 | + * changed. |
190 | 197 | */
|
191 | 198 | static List *
|
192 |
| -adjustJoinTreeList(Query *parsetree, int rt_index, bool *found) |
| 199 | +adjustJoinTreeList(Query *parsetree, bool removert, int rt_index) |
193 | 200 | {
|
194 | 201 | List *newjointree = listCopy(parsetree->jointree->fromlist);
|
195 | 202 | List *jjt;
|
196 | 203 |
|
197 |
| - *found = false; |
198 |
| - foreach(jjt, newjointree) |
| 204 | + if (removert) |
199 | 205 | {
|
200 |
| - RangeTblRef *rtr = lfirst(jjt); |
201 |
| - |
202 |
| - if (IsA(rtr, RangeTblRef) && rtr->rtindex == rt_index) |
| 206 | + foreach(jjt, newjointree) |
203 | 207 | {
|
204 |
| - newjointree = lremove(rtr, newjointree); |
205 |
| - *found = true; |
206 |
| - break; |
| 208 | + RangeTblRef *rtr = lfirst(jjt); |
| 209 | + |
| 210 | + if (IsA(rtr, RangeTblRef) && rtr->rtindex == rt_index) |
| 211 | + { |
| 212 | + newjointree = lremove(rtr, newjointree); |
| 213 | + break; |
| 214 | + } |
207 | 215 | }
|
208 | 216 | }
|
209 | 217 | return newjointree;
|
|
0 commit comments