Skip to content

Commit 7711e40

Browse files
committed
Make application of FOR UPDATE to a view work exactly like the parser's
transformForUpdate does: it should recurse into subqueries.
1 parent 0a844e8 commit 7711e40

File tree

1 file changed

+42
-22
lines changed

1 file changed

+42
-22
lines changed

src/backend/rewrite/rewriteHandler.c

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* 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 $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -38,6 +38,7 @@ static RewriteInfo *gatherRewriteMeta(Query *parsetree,
3838
CmdType event,
3939
bool instead_flag);
4040
static List *adjustJoinTreeList(Query *parsetree, int rt_index, bool *found);
41+
static void markQueryForUpdate(Query *qry, bool skipOldNew);
4142
static List *matchLocks(CmdType event, RuleLock *rulelocks,
4243
int varno, Query *parsetree);
4344
static Query *fireRIRrules(Query *parsetree);
@@ -263,7 +264,6 @@ ApplyRetrieveRule(Query *parsetree,
263264
Query *rule_action;
264265
RangeTblEntry *rte,
265266
*subrte;
266-
List *l;
267267

268268
if (length(rule->actions) != 1)
269269
elog(ERROR, "ApplyRetrieveRule: expected just one rule action");
@@ -308,8 +308,6 @@ ApplyRetrieveRule(Query *parsetree,
308308
*/
309309
if (intMember(rt_index, parsetree->rowMarks))
310310
{
311-
Index innerrti = 1;
312-
313311
/*
314312
* Remove the view from the list of rels that will actually be
315313
* marked FOR UPDATE by the executor. It will still be access-
@@ -320,29 +318,51 @@ ApplyRetrieveRule(Query *parsetree,
320318
/*
321319
* Set up the view's referenced tables as if FOR UPDATE.
322320
*/
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);
341322
}
342323

343324
return parsetree;
344325
}
345326

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+
346366

347367
/*
348368
* fireRIRonSubLink -

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