mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
Make application of FOR UPDATE to a view work exactly like the parser's
transformForUpdate does: it should recurse into subqueries.
This commit is contained in:
parent
0a844e84a1
commit
7711e40b9f
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.85 2000/12/06 23:55:18 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.86 2000/12/07 01:22:25 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -38,6 +38,7 @@ static RewriteInfo *gatherRewriteMeta(Query *parsetree,
|
|||||||
CmdType event,
|
CmdType event,
|
||||||
bool instead_flag);
|
bool instead_flag);
|
||||||
static List *adjustJoinTreeList(Query *parsetree, int rt_index, bool *found);
|
static List *adjustJoinTreeList(Query *parsetree, int rt_index, bool *found);
|
||||||
|
static void markQueryForUpdate(Query *qry, bool skipOldNew);
|
||||||
static List *matchLocks(CmdType event, RuleLock *rulelocks,
|
static List *matchLocks(CmdType event, RuleLock *rulelocks,
|
||||||
int varno, Query *parsetree);
|
int varno, Query *parsetree);
|
||||||
static Query *fireRIRrules(Query *parsetree);
|
static Query *fireRIRrules(Query *parsetree);
|
||||||
@ -263,7 +264,6 @@ ApplyRetrieveRule(Query *parsetree,
|
|||||||
Query *rule_action;
|
Query *rule_action;
|
||||||
RangeTblEntry *rte,
|
RangeTblEntry *rte,
|
||||||
*subrte;
|
*subrte;
|
||||||
List *l;
|
|
||||||
|
|
||||||
if (length(rule->actions) != 1)
|
if (length(rule->actions) != 1)
|
||||||
elog(ERROR, "ApplyRetrieveRule: expected just one rule action");
|
elog(ERROR, "ApplyRetrieveRule: expected just one rule action");
|
||||||
@ -308,8 +308,6 @@ ApplyRetrieveRule(Query *parsetree,
|
|||||||
*/
|
*/
|
||||||
if (intMember(rt_index, parsetree->rowMarks))
|
if (intMember(rt_index, parsetree->rowMarks))
|
||||||
{
|
{
|
||||||
Index innerrti = 1;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove the view from the list of rels that will actually be
|
* Remove the view from the list of rels that will actually be
|
||||||
* marked FOR UPDATE by the executor. It will still be access-
|
* marked FOR UPDATE by the executor. It will still be access-
|
||||||
@ -320,29 +318,51 @@ ApplyRetrieveRule(Query *parsetree,
|
|||||||
/*
|
/*
|
||||||
* Set up the view's referenced tables as if FOR UPDATE.
|
* Set up the view's referenced tables as if FOR UPDATE.
|
||||||
*/
|
*/
|
||||||
foreach(l, rule_action->rtable)
|
markQueryForUpdate(rule_action, true);
|
||||||
{
|
|
||||||
subrte = (RangeTblEntry *) lfirst(l);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* RTable of VIEW has two entries of VIEW itself - skip them!
|
|
||||||
* Also keep hands off of sub-subqueries.
|
|
||||||
*/
|
|
||||||
if (innerrti != PRS2_OLD_VARNO && innerrti != PRS2_NEW_VARNO &&
|
|
||||||
subrte->relid != InvalidOid)
|
|
||||||
{
|
|
||||||
if (!intMember(innerrti, rule_action->rowMarks))
|
|
||||||
rule_action->rowMarks = lappendi(rule_action->rowMarks,
|
|
||||||
innerrti);
|
|
||||||
subrte->checkForWrite = true;
|
|
||||||
}
|
|
||||||
innerrti++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsetree;
|
return parsetree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recursively mark all relations used by a view as FOR UPDATE.
|
||||||
|
*
|
||||||
|
* This may generate an invalid query, eg if some sub-query uses an
|
||||||
|
* aggregate. We leave it to the planner to detect that.
|
||||||
|
*
|
||||||
|
* NB: this must agree with the parser's transformForUpdate() routine.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
markQueryForUpdate(Query *qry, bool skipOldNew)
|
||||||
|
{
|
||||||
|
Index rti = 0;
|
||||||
|
List *l;
|
||||||
|
|
||||||
|
foreach(l, qry->rtable)
|
||||||
|
{
|
||||||
|
RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
|
||||||
|
|
||||||
|
rti++;
|
||||||
|
|
||||||
|
/* Ignore OLD and NEW entries if we are at top level of view */
|
||||||
|
if (skipOldNew &&
|
||||||
|
(rti == PRS2_OLD_VARNO || rti == PRS2_NEW_VARNO))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (rte->subquery)
|
||||||
|
{
|
||||||
|
/* FOR UPDATE of subquery is propagated to subquery's rels */
|
||||||
|
markQueryForUpdate(rte->subquery, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!intMember(rti, qry->rowMarks))
|
||||||
|
qry->rowMarks = lappendi(qry->rowMarks, rti);
|
||||||
|
rte->checkForWrite = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fireRIRonSubLink -
|
* fireRIRonSubLink -
|
||||||
|
Loading…
x
Reference in New Issue
Block a user