Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e4044ba

Browse files
committed
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.
1 parent 622736a commit e4044ba

File tree

2 files changed

+58
-30
lines changed

2 files changed

+58
-30
lines changed

src/backend/optimizer/plan/initsplan.c

+1-9
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.91 2003/09/25 06:58:00 petere Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.92 2003/11/05 22:00:46 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -91,14 +91,6 @@ add_base_rels_to_query(Query *root, Node *jtnode)
9191

9292
add_base_rels_to_query(root, j->larg);
9393
add_base_rels_to_query(root, j->rarg);
94-
95-
/*
96-
* Safety check: join RTEs should not be SELECT FOR UPDATE targets
97-
*/
98-
if (intMember(j->rtindex, root->rowMarks))
99-
ereport(ERROR,
100-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
101-
errmsg("SELECT FOR UPDATE cannot be applied to a join")));
10294
}
10395
else
10496
elog(ERROR, "unrecognized node type: %d",

src/backend/parser/analyze.c

+57-21
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.290 2003/10/02 06:32:45 petere Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.291 2003/11/05 22:00:46 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -2821,6 +2821,12 @@ CheckSelectForUpdate(Query *qry)
28212821
errmsg("SELECT FOR UPDATE is not allowed with aggregate functions")));
28222822
}
28232823

2824+
/*
2825+
* Convert FOR UPDATE name list into rowMarks list of integer relids
2826+
*
2827+
* NB: if you need to change this, see also markQueryForUpdate()
2828+
* in rewriteHandler.c.
2829+
*/
28242830
static void
28252831
transformForUpdate(Query *qry, List *forUpdate)
28262832
{
@@ -2833,23 +2839,30 @@ transformForUpdate(Query *qry, List *forUpdate)
28332839

28342840
if (lfirst(forUpdate) == NULL)
28352841
{
2836-
/* all tables used in query */
2842+
/* all regular tables used in query */
28372843
i = 0;
28382844
foreach(rt, qry->rtable)
28392845
{
28402846
RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
28412847

28422848
++i;
2843-
if (rte->rtekind == RTE_SUBQUERY)
2844-
{
2845-
/* FOR UPDATE of subquery is propagated to subquery's rels */
2846-
transformForUpdate(rte->subquery, makeList1(NULL));
2847-
}
2848-
else
2849+
switch (rte->rtekind)
28492850
{
2850-
if (!intMember(i, rowMarks)) /* avoid duplicates */
2851-
rowMarks = lappendi(rowMarks, i);
2852-
rte->checkForWrite = true;
2851+
case RTE_RELATION:
2852+
if (!intMember(i, rowMarks)) /* avoid duplicates */
2853+
rowMarks = lappendi(rowMarks, i);
2854+
rte->checkForWrite = true;
2855+
break;
2856+
case RTE_SUBQUERY:
2857+
/*
2858+
* FOR UPDATE of subquery is propagated to subquery's
2859+
* rels
2860+
*/
2861+
transformForUpdate(rte->subquery, makeList1(NULL));
2862+
break;
2863+
default:
2864+
/* ignore JOIN, SPECIAL, FUNCTION RTEs */
2865+
break;
28532866
}
28542867
}
28552868
}
@@ -2868,18 +2881,41 @@ transformForUpdate(Query *qry, List *forUpdate)
28682881
++i;
28692882
if (strcmp(rte->eref->aliasname, relname) == 0)
28702883
{
2871-
if (rte->rtekind == RTE_SUBQUERY)
2884+
switch (rte->rtekind)
28722885
{
2873-
/* propagate to subquery */
2874-
transformForUpdate(rte->subquery, makeList1(NULL));
2875-
}
2876-
else
2877-
{
2878-
if (!intMember(i, rowMarks)) /* avoid duplicates */
2879-
rowMarks = lappendi(rowMarks, i);
2880-
rte->checkForWrite = true;
2886+
case RTE_RELATION:
2887+
if (!intMember(i, rowMarks)) /* avoid duplicates */
2888+
rowMarks = lappendi(rowMarks, i);
2889+
rte->checkForWrite = true;
2890+
break;
2891+
case RTE_SUBQUERY:
2892+
/*
2893+
* FOR UPDATE of subquery is propagated to
2894+
* subquery's rels
2895+
*/
2896+
transformForUpdate(rte->subquery, makeList1(NULL));
2897+
break;
2898+
case RTE_JOIN:
2899+
ereport(ERROR,
2900+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2901+
errmsg("SELECT FOR UPDATE cannot be applied to a join")));
2902+
break;
2903+
case RTE_SPECIAL:
2904+
ereport(ERROR,
2905+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2906+
errmsg("SELECT FOR UPDATE cannot be applied to NEW or OLD")));
2907+
break;
2908+
case RTE_FUNCTION:
2909+
ereport(ERROR,
2910+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2911+
errmsg("SELECT FOR UPDATE cannot be applied to a function")));
2912+
break;
2913+
default:
2914+
elog(ERROR, "unrecognized RTE type: %d",
2915+
(int) rte->rtekind);
2916+
break;
28812917
}
2882-
break;
2918+
break; /* out of foreach loop */
28832919
}
28842920
}
28852921
if (rt == NIL)

0 commit comments

Comments
 (0)