7
7
*
8
8
*
9
9
* IDENTIFICATION
10
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.85 2000/12/06 23:55:18 tgl Exp $
10
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.86 2000/12/07 01:22:25 tgl Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -38,6 +38,7 @@ static RewriteInfo *gatherRewriteMeta(Query *parsetree,
38
38
CmdType event ,
39
39
bool instead_flag );
40
40
static List * adjustJoinTreeList (Query * parsetree , int rt_index , bool * found );
41
+ static void markQueryForUpdate (Query * qry , bool skipOldNew );
41
42
static List * matchLocks (CmdType event , RuleLock * rulelocks ,
42
43
int varno , Query * parsetree );
43
44
static Query * fireRIRrules (Query * parsetree );
@@ -263,7 +264,6 @@ ApplyRetrieveRule(Query *parsetree,
263
264
Query * rule_action ;
264
265
RangeTblEntry * rte ,
265
266
* subrte ;
266
- List * l ;
267
267
268
268
if (length (rule -> actions ) != 1 )
269
269
elog (ERROR , "ApplyRetrieveRule: expected just one rule action" );
@@ -308,8 +308,6 @@ ApplyRetrieveRule(Query *parsetree,
308
308
*/
309
309
if (intMember (rt_index , parsetree -> rowMarks ))
310
310
{
311
- Index innerrti = 1 ;
312
-
313
311
/*
314
312
* Remove the view from the list of rels that will actually be
315
313
* marked FOR UPDATE by the executor. It will still be access-
@@ -320,29 +318,51 @@ ApplyRetrieveRule(Query *parsetree,
320
318
/*
321
319
* Set up the view's referenced tables as if FOR UPDATE.
322
320
*/
323
- foreach (l , rule_action -> rtable )
324
- {
325
- subrte = (RangeTblEntry * ) lfirst (l );
326
-
327
- /*
328
- * RTable of VIEW has two entries of VIEW itself - skip them!
329
- * Also keep hands off of sub-subqueries.
330
- */
331
- if (innerrti != PRS2_OLD_VARNO && innerrti != PRS2_NEW_VARNO &&
332
- subrte -> relid != InvalidOid )
333
- {
334
- if (!intMember (innerrti , rule_action -> rowMarks ))
335
- rule_action -> rowMarks = lappendi (rule_action -> rowMarks ,
336
- innerrti );
337
- subrte -> checkForWrite = true;
338
- }
339
- innerrti ++ ;
340
- }
321
+ markQueryForUpdate (rule_action , true);
341
322
}
342
323
343
324
return parsetree ;
344
325
}
345
326
327
+ /*
328
+ * Recursively mark all relations used by a view as FOR UPDATE.
329
+ *
330
+ * This may generate an invalid query, eg if some sub-query uses an
331
+ * aggregate. We leave it to the planner to detect that.
332
+ *
333
+ * NB: this must agree with the parser's transformForUpdate() routine.
334
+ */
335
+ static void
336
+ markQueryForUpdate (Query * qry , bool skipOldNew )
337
+ {
338
+ Index rti = 0 ;
339
+ List * l ;
340
+
341
+ foreach (l , qry -> rtable )
342
+ {
343
+ RangeTblEntry * rte = (RangeTblEntry * ) lfirst (l );
344
+
345
+ rti ++ ;
346
+
347
+ /* Ignore OLD and NEW entries if we are at top level of view */
348
+ if (skipOldNew &&
349
+ (rti == PRS2_OLD_VARNO || rti == PRS2_NEW_VARNO ))
350
+ continue ;
351
+
352
+ if (rte -> subquery )
353
+ {
354
+ /* FOR UPDATE of subquery is propagated to subquery's rels */
355
+ markQueryForUpdate (rte -> subquery , false);
356
+ }
357
+ else
358
+ {
359
+ if (!intMember (rti , qry -> rowMarks ))
360
+ qry -> rowMarks = lappendi (qry -> rowMarks , rti );
361
+ rte -> checkForWrite = true;
362
+ }
363
+ }
364
+ }
365
+
346
366
347
367
/*
348
368
* fireRIRonSubLink -
0 commit comments