aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/plan/initsplan.c10
-rw-r--r--src/backend/parser/analyze.c78
2 files changed, 58 insertions, 30 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index eec153b70d3..58a9e16eb65 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.91 2003/09/25 06:58:00 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.92 2003/11/05 22:00:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -91,14 +91,6 @@ add_base_rels_to_query(Query *root, Node *jtnode)
add_base_rels_to_query(root, j->larg);
add_base_rels_to_query(root, j->rarg);
-
- /*
- * Safety check: join RTEs should not be SELECT FOR UPDATE targets
- */
- if (intMember(j->rtindex, root->rowMarks))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("SELECT FOR UPDATE cannot be applied to a join")));
}
else
elog(ERROR, "unrecognized node type: %d",
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index d6fbc6b3d76..f30fcdd2793 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.290 2003/10/02 06:32:45 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.291 2003/11/05 22:00:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2821,6 +2821,12 @@ CheckSelectForUpdate(Query *qry)
errmsg("SELECT FOR UPDATE is not allowed with aggregate functions")));
}
+/*
+ * Convert FOR UPDATE name list into rowMarks list of integer relids
+ *
+ * NB: if you need to change this, see also markQueryForUpdate()
+ * in rewriteHandler.c.
+ */
static void
transformForUpdate(Query *qry, List *forUpdate)
{
@@ -2833,23 +2839,30 @@ transformForUpdate(Query *qry, List *forUpdate)
if (lfirst(forUpdate) == NULL)
{
- /* all tables used in query */
+ /* all regular tables used in query */
i = 0;
foreach(rt, qry->rtable)
{
RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
++i;
- if (rte->rtekind == RTE_SUBQUERY)
- {
- /* FOR UPDATE of subquery is propagated to subquery's rels */
- transformForUpdate(rte->subquery, makeList1(NULL));
- }
- else
+ switch (rte->rtekind)
{
- if (!intMember(i, rowMarks)) /* avoid duplicates */
- rowMarks = lappendi(rowMarks, i);
- rte->checkForWrite = true;
+ case RTE_RELATION:
+ if (!intMember(i, rowMarks)) /* avoid duplicates */
+ rowMarks = lappendi(rowMarks, i);
+ rte->checkForWrite = true;
+ break;
+ case RTE_SUBQUERY:
+ /*
+ * FOR UPDATE of subquery is propagated to subquery's
+ * rels
+ */
+ transformForUpdate(rte->subquery, makeList1(NULL));
+ break;
+ default:
+ /* ignore JOIN, SPECIAL, FUNCTION RTEs */
+ break;
}
}
}
@@ -2868,18 +2881,41 @@ transformForUpdate(Query *qry, List *forUpdate)
++i;
if (strcmp(rte->eref->aliasname, relname) == 0)
{
- if (rte->rtekind == RTE_SUBQUERY)
+ switch (rte->rtekind)
{
- /* propagate to subquery */
- transformForUpdate(rte->subquery, makeList1(NULL));
- }
- else
- {
- if (!intMember(i, rowMarks)) /* avoid duplicates */
- rowMarks = lappendi(rowMarks, i);
- rte->checkForWrite = true;
+ case RTE_RELATION:
+ if (!intMember(i, rowMarks)) /* avoid duplicates */
+ rowMarks = lappendi(rowMarks, i);
+ rte->checkForWrite = true;
+ break;
+ case RTE_SUBQUERY:
+ /*
+ * FOR UPDATE of subquery is propagated to
+ * subquery's rels
+ */
+ transformForUpdate(rte->subquery, makeList1(NULL));
+ break;
+ case RTE_JOIN:
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("SELECT FOR UPDATE cannot be applied to a join")));
+ break;
+ case RTE_SPECIAL:
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("SELECT FOR UPDATE cannot be applied to NEW or OLD")));
+ break;
+ case RTE_FUNCTION:
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("SELECT FOR UPDATE cannot be applied to a function")));
+ break;
+ default:
+ elog(ERROR, "unrecognized RTE type: %d",
+ (int) rte->rtekind);
+ break;
}
- break;
+ break; /* out of foreach loop */
}
}
if (rt == NIL)