aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDean Rasheed <dean.a.rasheed@gmail.com>2022-07-07 13:07:57 +0100
committerDean Rasheed <dean.a.rasheed@gmail.com>2022-07-07 13:07:57 +0100
commitf9c655d647427b45ae0d7bd9baf3551a013b8ea1 (patch)
treecd419952bee872b8eb6d4d97be45313499681072
parent7c2b79c2bc22259a2de086af65fc0d8f0cd7a0f2 (diff)
downloadpostgresql-f9c655d647427b45ae0d7bd9baf3551a013b8ea1.tar.gz
postgresql-f9c655d647427b45ae0d7bd9baf3551a013b8ea1.zip
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
-rw-r--r--src/backend/parser/analyze.c9
-rw-r--r--src/test/regress/expected/join.out8
-rw-r--r--src/test/regress/sql/join.sql6
3 files changed, 23 insertions, 0 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index d243e0284a5..9f59b4af357 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -2809,6 +2809,15 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
++i;
if (!rte->inFromCl)
continue;
+
+ /*
+ * A join RTE without an alias is not visible as a relation
+ * name and needs to be skipped (otherwise it might hide a
+ * base relation with the same name).
+ */
+ if (rte->rtekind == RTE_JOIN && rte->alias == NULL)
+ continue;
+
if (strcmp(rte->eref->aliasname, thisrel->relname) == 0)
{
switch (rte->rtekind)
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index d2db9804e41..610e70d1cfd 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -2449,6 +2449,14 @@ ERROR: column t1.x does not exist
LINE 1: select t1.x from t1 join t3 on (t1.a = t3.x);
^
HINT: Perhaps you meant to reference the column "t3.x".
+-- Test matching of locking clause with wrong alias
+select t1.*, t2.*, unnamed_join.* from
+ t1 join t2 on (t1.a = t2.a), t3 as unnamed_join
+ for update of unnamed_join;
+ a | b | a | b | x | y
+---+---+---+---+---+---
+(0 rows)
+
--
-- regression test for 8.1 merge right join bug
--
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index 16c9b2e4322..2fff1a882e1 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -509,6 +509,12 @@ select * from t1 left join t2 on (t1.a = t2.a);
select t1.x from t1 join t3 on (t1.a = t3.x);
+-- Test matching of locking clause with wrong alias
+
+select t1.*, t2.*, unnamed_join.* from
+ t1 join t2 on (t1.a = t2.a), t3 as unnamed_join
+ for update of unnamed_join;
+
--
-- regression test for 8.1 merge right join bug
--