Commit e4044ba2 authored by Tom Lane's avatar Tom Lane

Fix for this problem:

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.
parent 622736aa
......@@ -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",
......
......@@ -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)
{
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)
{
/* propagate to subquery */
transformForUpdate(rte->subquery, makeList1(NULL));
}
else
switch (rte->rtekind)
{
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; /* out of foreach loop */
}
}
if (rt == NIL)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment