1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

Fix join alias expansion in lateral TABLESAMPLE clauses

preprocess_expression skips flatten_join_alias_vars for TABLESAMPLE
clauses, on the assumption that they cannot contain Vars of the
current query level.  That's not true once a LATERAL subquery
containing a sampled relation has been pulled up: the relation's
TABLESAMPLE clause then becomes a lateral reference of this level, and
if it referred to a join alias Var, that Var is left unexpanded.
extract_lateral_references then pulls the join alias Var out as a
lateral reference and fails with "no relation entry for relid N".

To fix, treat such clauses like lateral function and VALUES RTEs:
introduce EXPRKIND_TABLESAMPLE_LATERAL, used for the TABLESAMPLE
clause of a lateral relation RTE, and keep skipping the alias
expansion only for the non-lateral kind.

Back-patch to all supported branches, as this dates back to the
introduction of TABLESAMPLE.

Author: Richard Guo <guofenglinux@gmail.com>
Reviewed-by: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Discussion: https://postgr.es/m/CAMbWs4834TwOtyyycyvja3MuOBkfpXy3dFAL0zt_vcM1KtqV-Q@mail.gmail.com
Backpatch-through: 14
This commit is contained in:
Richard Guo
2026-10-04 16:07:10 +09:00
parent 5a73125874
commit 011dd50957
3 changed files with 54 additions and 4 deletions

View File

@@ -89,9 +89,10 @@ create_upper_paths_hook_type create_upper_paths_hook = NULL;
#define EXPRKIND_APPINFO 7
#define EXPRKIND_PHV 8
#define EXPRKIND_TABLESAMPLE 9
#define EXPRKIND_ARBITER_ELEM 10
#define EXPRKIND_TABLEFUNC 11
#define EXPRKIND_TABLEFUNC_LATERAL 12
#define EXPRKIND_TABLESAMPLE_LATERAL 10
#define EXPRKIND_ARBITER_ELEM 11
#define EXPRKIND_TABLEFUNC 12
#define EXPRKIND_TABLEFUNC_LATERAL 13
/* Passthrough data for standard_qp_callback */
typedef struct
@@ -915,10 +916,15 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
if (rte->rtekind == RTE_RELATION)
{
if (rte->tablesample)
{
/* Preprocess the tablesample expression(s) fully */
kind = rte->lateral ? EXPRKIND_TABLESAMPLE_LATERAL :
EXPRKIND_TABLESAMPLE;
rte->tablesample = (TableSampleClause *)
preprocess_expression(root,
(Node *) rte->tablesample,
EXPRKIND_TABLESAMPLE);
kind);
}
}
else if (rte->rtekind == RTE_SUBQUERY)
{

View File

@@ -279,6 +279,38 @@ select pct, count(unique1) from
100 | 10000
(1 row)
-- check that a join alias Var in a pulled-up LATERAL subquery's TABLESAMPLE
-- clause gets flattened
explain (costs off)
select pct, count(unique1) from
((values (0)) v(pct) full join (values (100)) w(pct) using (pct)),
lateral (select * from tenk1 tablesample bernoulli (pct)) ss
group by pct order by pct;
QUERY PLAN
----------------------------------------------------------------
GroupAggregate
Group Key: (COALESCE((0), (100)))
-> Sort
Sort Key: (COALESCE((0), (100)))
-> Nested Loop
-> Hash Full Join
Hash Cond: ((0) = (100))
-> Result
-> Hash
-> Result
-> Sample Scan on tenk1
Sampling: bernoulli (COALESCE((0), (100)))
(12 rows)
select pct, count(unique1) from
((values (0)) v(pct) full join (values (100)) w(pct) using (pct)),
lateral (select * from tenk1 tablesample bernoulli (pct)) ss
group by pct order by pct;
pct | count
-----+-------
100 | 10000
(1 row)
-- errors
SELECT id FROM test_tablesample TABLESAMPLE FOOBAR (1);
ERROR: tablesample method foobar does not exist

View File

@@ -82,6 +82,18 @@ select pct, count(unique1) from
lateral (select * from tenk1 tablesample system (pct)) ss
group by pct;
-- check that a join alias Var in a pulled-up LATERAL subquery's TABLESAMPLE
-- clause gets flattened
explain (costs off)
select pct, count(unique1) from
((values (0)) v(pct) full join (values (100)) w(pct) using (pct)),
lateral (select * from tenk1 tablesample bernoulli (pct)) ss
group by pct order by pct;
select pct, count(unique1) from
((values (0)) v(pct) full join (values (100)) w(pct) using (pct)),
lateral (select * from tenk1 tablesample bernoulli (pct)) ss
group by pct order by pct;
-- errors
SELECT id FROM test_tablesample TABLESAMPLE FOOBAR (1);