v2-0001-Fix-planner-error-when-estimating-SubPlan-cost.patch
application/octet-stream
Filename: v2-0001-Fix-planner-error-when-estimating-SubPlan-cost.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v2-0001
Subject: Fix planner error when estimating SubPlan cost
| File | + | − |
|---|---|---|
| src/backend/optimizer/path/costsize.c | 16 | 2 |
| src/test/regress/expected/subselect.out | 19 | 0 |
| src/test/regress/sql/subselect.sql | 9 | 0 |
From 3c333a5e3984ca188e82e3408251e989ffd47104 Mon Sep 17 00:00:00 2001
From: Richard Guo <guofenglinux@gmail.com>
Date: Tue, 2 Sep 2025 12:18:12 +0900
Subject: [PATCH v2] Fix planner error when estimating SubPlan cost
SubPlan nodes are typically built very early, before any RelOptInfos
have been constructed for the parent query level. As a result, the
simple_rel_array in the parent root has not yet been initialized.
Currently, during cost estimation of a SubPlan's testexpr, we may call
examine_variable() to look up statistical data about the expressions.
This can lead to "no relation entry for relid" errors.
To fix, pass root as NULL to cost_qual_eval() in cost_subplan(), since
the root does not yet contain enough information to safely consult
statistics.
One exception is SubPlan nodes built for the initplans of MIN/MAX
aggregates from indexes. In this case, having a NULL root is safe
because testexpr will be NULL. Additionally, an initplan will by
definition not consult anything from the parent plan.
---
src/backend/optimizer/path/costsize.c | 18 ++++++++++++++++--
src/test/regress/expected/subselect.out | 19 +++++++++++++++++++
src/test/regress/sql/subselect.sql | 9 +++++++++
3 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 783dca8a4ac..94077e6a006 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -4570,10 +4570,24 @@ cost_subplan(PlannerInfo *root, SubPlan *subplan, Plan *plan)
{
QualCost sp_cost;
- /* Figure any cost for evaluating the testexpr */
+ /*
+ * Figure any cost for evaluating the testexpr.
+ *
+ * Usually, SubPlan nodes are built very early, before we have constructed
+ * any RelOptInfos for the parent query level, which means the parent root
+ * does not yet contain enough information to safely consult statistics.
+ * Therefore, we pass root as NULL here. cost_qual_eval() is already
+ * well-equipped to handle a NULL root.
+ *
+ * One exception is SubPlan nodes built for the initplans of MIN/MAX
+ * aggregates from indexes (cf. SS_make_initplan_from_plan). In this
+ * case, having a NULL root is safe because testexpr will be NULL.
+ * Besides, an initplan will by definition not consult anything from the
+ * parent plan.
+ */
cost_qual_eval(&sp_cost,
make_ands_implicit((Expr *) subplan->testexpr),
- root);
+ NULL);
if (subplan->useHashTable)
{
diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out
index 0563d0cd5a1..029a670bae7 100644
--- a/src/test/regress/expected/subselect.out
+++ b/src/test/regress/expected/subselect.out
@@ -979,6 +979,25 @@ select (select (a.*)::text) from view_a a;
(42)
(1 row)
+--
+-- Test case for bug #19037: no relation entry for relid N
+--
+explain (costs off)
+select ((1 = any(array_agg(f1)))::int) = any (select 0) from int4_tbl;
+ QUERY PLAN
+----------------------------
+ Aggregate
+ -> Seq Scan on int4_tbl
+ SubPlan 1
+ -> Result
+(4 rows)
+
+select ((1 = any(array_agg(f1)))::int) = any (select 0) from int4_tbl;
+ ?column?
+----------
+ t
+(1 row)
+
--
-- Check that whole-row Vars reading the result of a subselect don't include
-- any junk columns therein
diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql
index a6d276a115b..46ae3665f1f 100644
--- a/src/test/regress/sql/subselect.sql
+++ b/src/test/regress/sql/subselect.sql
@@ -479,6 +479,15 @@ select (select view_a) from view_a;
select (select (select view_a)) from view_a;
select (select (a.*)::text) from view_a a;
+--
+-- Test case for bug #19037: no relation entry for relid N
+--
+
+explain (costs off)
+select ((1 = any(array_agg(f1)))::int) = any (select 0) from int4_tbl;
+
+select ((1 = any(array_agg(f1)))::int) = any (select 0) from int4_tbl;
+
--
-- Check that whole-row Vars reading the result of a subselect don't include
-- any junk columns therein
--
2.39.5 (Apple Git-154)