git.postgresql.org Git - postgresql.git/commitdiff

git projects / postgresql.git / commitdiff
? search:
summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 622736a)
Fix for this problem:
Wed, 5 Nov 2003 22:00:46 +0000 (22:00 +0000)
Wed, 5 Nov 2003 22:00:46 +0000 (22:00 +0000)
regression=# select 1 from tenk1 ta cross join tenk1 tb for update;
ERROR: no relation entry for relid 3

7.3 said "SELECT FOR UPDATE cannot be applied to a join", which was better
but still wrong, considering that 7.2 took the query just fine. Fix by
making transformForUpdate() ignore JOIN and other special RTE types,
rather than trying to mark them FOR UPDATE. The actual error message now
only appears if you explicitly name the join in FOR UPDATE.


diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index eec153b70d3338552b124f52682da8b7813b59c6..58a9e16eb65f9369657e9ab119099b3e8c58ee81 100644 (file)
--- 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 d6fbc6b3d76768377ffd40a04cde408bfd589c6c..f30fcdd2793fea41e81715f901a4a67762afae50 100644 (file)
--- 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)
This is the main PostgreSQL git repository.
RSS Atom

AltStyle によって変換されたページ (->オリジナル) /