From df3db35ab2b5127790b9a9b84a61c8b873df250d Mon Sep 17 00:00:00 2001 From: Richard Guo Date: Wed, 16 Sep 2026 14:56:15 +0900 Subject: [PATCH v1] 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. --- src/backend/optimizer/plan/planner.c | 16 ++++++++---- src/test/regress/expected/tablesample.out | 32 +++++++++++++++++++++++ src/test/regress/sql/tablesample.sql | 12 +++++++++ 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 8d30131855a..21dc4c8363e 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -94,10 +94,11 @@ 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_GROUPEXPR 13 +#define EXPRKIND_TABLESAMPLE_LATERAL 10 +#define EXPRKIND_ARBITER_ELEM 11 +#define EXPRKIND_TABLEFUNC 12 +#define EXPRKIND_TABLEFUNC_LATERAL 13 +#define EXPRKIND_GROUPEXPR 14 /* * Data specific to grouping sets @@ -1111,10 +1112,15 @@ subquery_planner(PlannerGlobal *glob, Query *parse, char *plan_name, 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) { diff --git a/src/test/regress/expected/tablesample.out b/src/test/regress/expected/tablesample.out index 9ff4611640c..589d5c3054c 100644 --- a/src/test/regress/expected/tablesample.out +++ b/src/test/regress/expected/tablesample.out @@ -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 diff --git a/src/test/regress/sql/tablesample.sql b/src/test/regress/sql/tablesample.sql index aa17994277c..7dd7738e530 100644 --- a/src/test/regress/sql/tablesample.sql +++ b/src/test/regress/sql/tablesample.sql @@ -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); -- 2.37.1 (Apple Git-137.1)