aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-03-01 18:50:42 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-03-01 18:50:42 +0000
commit3b14809f9281bf258c281f6ebcc8b6b7b408a467 (patch)
tree31066cb4b6797a331231437b5cd25b23e6a94d5c
parente9a97570fadeb79d5a21086399bdf5b48d924b17 (diff)
downloadpostgresql-3b14809f9281bf258c281f6ebcc8b6b7b408a467.tar.gz
postgresql-3b14809f9281bf258c281f6ebcc8b6b7b408a467.zip
Fix markQueryForLocking() to work correctly in the presence of nested views.
It has been wrong for this case since it was first written for 7.1 :-( Per report from Pavel HanĂ¡k.
-rw-r--r--src/backend/rewrite/rewriteHandler.c56
1 files changed, 36 insertions, 20 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 969188acdb7..bf244b7e63a 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.158.2.2 2005/11/23 17:21:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.158.2.3 2007/03/01 18:50:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -52,8 +52,8 @@ static TargetEntry *process_matched_tle(TargetEntry *src_tle,
TargetEntry *prior_tle,
const char *attrName);
static Node *get_assignment_input(Node *node);
-static void markQueryForLocking(Query *qry, bool forUpdate, bool noWait,
- bool skipOldNew);
+static void markQueryForLocking(Query *qry, Node *jtnode,
+ bool forUpdate, bool noWait);
static List *matchLocks(CmdType event, RuleLock *rulelocks,
int varno, Query *parsetree);
static Query *fireRIRrules(Query *parsetree, List *activeRIRs);
@@ -966,8 +966,8 @@ ApplyRetrieveRule(Query *parsetree,
/*
* Set up the view's referenced tables as if FOR UPDATE/SHARE.
*/
- markQueryForLocking(rule_action, parsetree->forUpdate,
- parsetree->rowNoWait, true);
+ markQueryForLocking(rule_action, (Node *) rule_action->jointree,
+ parsetree->forUpdate, parsetree->rowNoWait);
}
return parsetree;
@@ -979,14 +979,15 @@ ApplyRetrieveRule(Query *parsetree,
* 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 transformLocking() routine.
+ * NB: this must agree with the parser's transformLockingClause() routine.
+ * However, unlike the parser we have to be careful not to mark a view's
+ * OLD and NEW rels for updating. The best way to handle that seems to be
+ * to scan the jointree to determine which rels are used.
*/
static void
-markQueryForLocking(Query *qry, bool forUpdate, bool noWait, bool skipOldNew)
+markQueryForLocking(Query *qry, Node *jtnode, bool forUpdate, bool noWait)
{
- Index rti = 0;
- ListCell *l;
-
+ /* when recursing, this check is redundant; cheap enough not to worry */
if (qry->rowMarks)
{
if (forUpdate != qry->forUpdate)
@@ -1001,16 +1002,12 @@ markQueryForLocking(Query *qry, bool forUpdate, bool noWait, bool skipOldNew)
qry->forUpdate = forUpdate;
qry->rowNoWait = noWait;
- foreach(l, qry->rtable)
+ if (jtnode == NULL)
+ return;
+ if (IsA(jtnode, RangeTblRef))
{
- 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;
+ int rti = ((RangeTblRef *) jtnode)->rtindex;
+ RangeTblEntry *rte = rt_fetch(rti, qry->rtable);
if (rte->rtekind == RTE_RELATION)
{
@@ -1020,9 +1017,28 @@ markQueryForLocking(Query *qry, bool forUpdate, bool noWait, bool skipOldNew)
else if (rte->rtekind == RTE_SUBQUERY)
{
/* FOR UPDATE/SHARE of subquery is propagated to subquery's rels */
- markQueryForLocking(rte->subquery, forUpdate, noWait, false);
+ markQueryForLocking(rte->subquery, (Node *) rte->subquery->jointree,
+ forUpdate, noWait);
}
}
+ else if (IsA(jtnode, FromExpr))
+ {
+ FromExpr *f = (FromExpr *) jtnode;
+ ListCell *l;
+
+ foreach(l, f->fromlist)
+ markQueryForLocking(qry, lfirst(l), forUpdate, noWait);
+ }
+ else if (IsA(jtnode, JoinExpr))
+ {
+ JoinExpr *j = (JoinExpr *) jtnode;
+
+ markQueryForLocking(qry, j->larg, forUpdate, noWait);
+ markQueryForLocking(qry, j->rarg, forUpdate, noWait);
+ }
+ else
+ elog(ERROR, "unrecognized node type: %d",
+ (int) nodeTag(jtnode));
}