0001-Fix-no-relation-entry-for-relid-0-in-nested-UNION-AL.patch
application/octet-stream
Filename: 0001-Fix-no-relation-entry-for-relid-0-in-nested-UNION-AL.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 0001
Subject: Fix "no relation entry for relid 0" in nested UNION ALL with array coercion.
| File | + | − |
|---|---|---|
| src/backend/utils/adt/selfuncs.c | 9 | 0 |
| src/test/regress/expected/union.out | 11 | 0 |
| src/test/regress/sql/union.sql | 5 | 0 |
From 09cae95e24996e34ca12e38133150e71e351edcc Mon Sep 17 00:00:00 2001
From: Tender Wang <tndrwang@gmail.com>
Date: Sat, 11 Apr 2026 09:25:50 +0800
Subject: [PATCH] Fix "no relation entry for relid 0" in nested UNION ALL with
array coercion.
This patch addresses an issue where a three-branch (or more) UNION ALL
fails during the planning/costing stage if it involves array type
promotion.
The error "no relation entry for relid 0" occurs because when UNION ALL
branches are nested, the planner may generate a Var node with varno 0
to represent a coerced sub-tree (e.g., promoting int[] to bigint[]).
Previously, the costing logic for array expressions did not account
for these Vars with varno = 0, leading to a lookup failure.
Example of failing query:
SELECT NULL::int[] UNION ALL
SELECT NULL::int[] UNION ALL
SELECT NULL::bigint[];
The fix ensures that such Var nodes are recognized and assigned a
default cost, allowing the planner to proceed correctly.
---
src/backend/utils/adt/selfuncs.c | 9 +++++++++
src/test/regress/expected/union.out | 11 +++++++++++
src/test/regress/sql/union.sql | 5 +++++
3 files changed, 25 insertions(+)
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 4160d2d6e24..adccb13dd0d 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -2265,6 +2265,15 @@ estimate_array_length(PlannerInfo *root, Node *arrayexpr)
AttStatsSlot sslot;
double nelem = 0;
+ /*
+ * Handle Var nodes with varno 0:
+ * in cases like (int[] UNION ALL int[]) UNION ALL bigint[].
+ * The planner may generate a Var node with varno 0 when coercing
+ * the result of nested set operations. See recurse_set_operations().
+ */
+ if (IsA(arrayexpr, Var) && ((Var *) arrayexpr)->varno == 0 )
+ return 10;
+
examine_variable(root, arrayexpr, 0, &vardata);
if (HeapTupleIsValid(vardata.statsTuple))
{
diff --git a/src/test/regress/expected/union.out b/src/test/regress/expected/union.out
index 709c85f2294..2c7643b5289 100644
--- a/src/test/regress/expected/union.out
+++ b/src/test/regress/expected/union.out
@@ -1661,3 +1661,14 @@ on true limit 1;
-> Result
(6 rows)
+--
+-- Test nested UNION ALL with type coercion
+--
+SELECT NULL::int[] UNION ALL SELECT NULL::int[] UNION ALL SELECT NULL::bigint[];
+ int4
+------
+
+
+
+(3 rows)
+
diff --git a/src/test/regress/sql/union.sql b/src/test/regress/sql/union.sql
index d0c70fafbea..cc5fd029fa3 100644
--- a/src/test/regress/sql/union.sql
+++ b/src/test/regress/sql/union.sql
@@ -664,3 +664,8 @@ select * from tenk1 t1
left join lateral
(select t1.tenthous from tenk2 t2 union all (values(1)))
on true limit 1;
+
+--
+-- Test nested UNION ALL with type coercion
+--
+SELECT NULL::int[] UNION ALL SELECT NULL::int[] UNION ALL SELECT NULL::bigint[];
\ No newline at end of file
--
2.34.1