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

Commit 8d367a4

Browse files
committed
Fix alias matching in transformLockingClause().
When locking a specific named relation for a FOR [KEY] UPDATE/SHARE clause, transformLockingClause() finds the relation to lock by scanning the rangetable for an RTE with a matching eref->aliasname. However, it failed to account for the visibility rules of a join RTE. If a join RTE doesn't have a user-supplied alias, it will have a generated eref->aliasname of "unnamed_join" that is not visible as a relation name in the parse namespace. Such an RTE needs to be skipped, otherwise it might be found in preference to a regular base relation with a user-supplied alias of "unnamed_join", preventing it from being locked. In addition, if a join RTE doesn't have a user-supplied alias, but does have a join_using_alias, then the RTE needs to be matched using that alias rather than the generated eref->aliasname, otherwise a misleading "relation not found" error will be reported rather than a "join cannot be locked" error. Backpatch all the way, except for the second part which only goes back to 14, where JOIN USING aliases were added. Dean Rasheed, reviewed by Tom Lane. Discussion: https://postgr.es/m/CAEZATCUY_KOBnqxbTSPf=7fz9HWPnZ5Xgb9SwYzZ8rFXe7nb=w@mail.gmail.com
1 parent 82699ed commit 8d367a4

File tree

3 files changed

+73
-1
lines changed

3 files changed

+73
-1
lines changed

src/backend/parser/analyze.c

+18-1
Original file line numberDiff line numberDiff line change
@@ -3291,11 +3291,28 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
32913291
foreach(rt, qry->rtable)
32923292
{
32933293
RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
3294+
char *rtename;
32943295

32953296
++i;
32963297
if (!rte->inFromCl)
32973298
continue;
3298-
if (strcmp(rte->eref->aliasname, thisrel->relname) == 0)
3299+
3300+
/*
3301+
* A join RTE without an alias is not visible as a relation
3302+
* name and needs to be skipped (otherwise it might hide a
3303+
* base relation with the same name), except if it has a USING
3304+
* alias, which *is* visible.
3305+
*/
3306+
if (rte->rtekind == RTE_JOIN && rte->alias == NULL)
3307+
{
3308+
if (rte->join_using_alias == NULL)
3309+
continue;
3310+
rtename = rte->join_using_alias->aliasname;
3311+
}
3312+
else
3313+
rtename = rte->eref->aliasname;
3314+
3315+
if (strcmp(rtename, thisrel->relname) == 0)
32993316
{
33003317
switch (rte->rtekind)
33013318
{

src/test/regress/expected/join.out

+33
Original file line numberDiff line numberDiff line change
@@ -2501,6 +2501,39 @@ ERROR: column t1.x does not exist
25012501
LINE 1: select t1.x from t1 join t3 on (t1.a = t3.x);
25022502
^
25032503
HINT: Perhaps you meant to reference the column "t3.x".
2504+
-- Test matching of locking clause with wrong alias
2505+
select t1.*, t2.*, unnamed_join.* from
2506+
t1 join t2 on (t1.a = t2.a), t3 as unnamed_join
2507+
for update of unnamed_join;
2508+
a | b | a | b | x | y
2509+
---+---+---+---+---+---
2510+
(0 rows)
2511+
2512+
select foo.*, unnamed_join.* from
2513+
t1 join t2 using (a) as foo, t3 as unnamed_join
2514+
for update of unnamed_join;
2515+
a | x | y
2516+
---+---+---
2517+
(0 rows)
2518+
2519+
select foo.*, unnamed_join.* from
2520+
t1 join t2 using (a) as foo, t3 as unnamed_join
2521+
for update of foo;
2522+
ERROR: FOR UPDATE cannot be applied to a join
2523+
LINE 3: for update of foo;
2524+
^
2525+
select bar.*, unnamed_join.* from
2526+
(t1 join t2 using (a) as foo) as bar, t3 as unnamed_join
2527+
for update of foo;
2528+
ERROR: relation "foo" in FOR UPDATE clause not found in FROM clause
2529+
LINE 3: for update of foo;
2530+
^
2531+
select bar.*, unnamed_join.* from
2532+
(t1 join t2 using (a) as foo) as bar, t3 as unnamed_join
2533+
for update of bar;
2534+
ERROR: FOR UPDATE cannot be applied to a join
2535+
LINE 3: for update of bar;
2536+
^
25042537
--
25052538
-- regression test for 8.1 merge right join bug
25062539
--

src/test/regress/sql/join.sql

+22
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,28 @@ select * from t1 left join t2 on (t1.a = t2.a);
520520

521521
select t1.x from t1 join t3 on (t1.a = t3.x);
522522

523+
-- Test matching of locking clause with wrong alias
524+
525+
select t1.*, t2.*, unnamed_join.* from
526+
t1 join t2 on (t1.a = t2.a), t3 as unnamed_join
527+
for update of unnamed_join;
528+
529+
select foo.*, unnamed_join.* from
530+
t1 join t2 using (a) as foo, t3 as unnamed_join
531+
for update of unnamed_join;
532+
533+
select foo.*, unnamed_join.* from
534+
t1 join t2 using (a) as foo, t3 as unnamed_join
535+
for update of foo;
536+
537+
select bar.*, unnamed_join.* from
538+
(t1 join t2 using (a) as foo) as bar, t3 as unnamed_join
539+
for update of foo;
540+
541+
select bar.*, unnamed_join.* from
542+
(t1 join t2 using (a) as foo) as bar, t3 as unnamed_join
543+
for update of bar;
544+
523545
--
524546
-- regression test for 8.1 merge right join bug
525547
--

0 commit comments

Comments
 (0)