Subject: pg17: XX000: no relation entry for relid 0

From: Justin Pryzby <[email-masked]>
Date: Fri, 10 Apr 2026 05:54:42 -0500

CREATE VIEW x AS SELECT NULL::int[]
UNION ALL SELECT NULL::int[]
UNION ALL SELECT ARRAY[NULL::bigint];

SELECT FROM x;
ERROR:  XX000: no relation entry for relid 0

Since 9391f7152.

-- 
Justin

---

From: Tender Wang <[email-masked]>
Date: Fri, 10 Apr 2026 20:49:24 +0800

> ERROR:  XX000: no relation entry for relid 0
The varno = 0 is from below code:

*pTargetList = generate_setop_tlist(colTypes, colCollations,
                                                0,
                                                false,
                                                *pTargetList,
                                                refnames_tlist,
                                                &trivial_tlist);
            *istrivial_tlist = trivial_tlist;
            target = create_pathtarget(root, *pTargetList);

in recurse_set_operations().
When calling set_pathtarget_cost_width(), we estimate the length of
the array that would enter estimate_array_length().
Before 9391f7152, we returned 10 directly.  But now, we see if we can
find any statistics about it.
In examine_variable(), try to find base_rel in find_base_rel(), error
reported. Because the varno of the Var is 0.

I didn't think too much at now, a quick fix as below:
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 4160d2d6e24..ff93fc3ac8a 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -2265,6 +2265,9 @@ estimate_array_length(PlannerInfo *root, Node *arrayexpr)
                AttStatsSlot sslot;
                double          nelem = 0;

+               if (IsA(arrayexpr, Var) && ((Var *) arrayexpr)->varno == 0)
+                       return 10;
+
                examine_variable(root, arrayexpr, 0, &vardata);
                if (HeapTupleIsValid(vardata.statsTuple))
                {

Any thoughts?

-- 
Thanks,
Tender Wang

---

From: Richard Guo <[email-masked]>
Date: Fri, 10 Apr 2026 23:38:50 +0900

> > ERROR:  XX000: no relation entry for relid 0

Nice catch.  It seems that we need at least three branches to
reproduce this, so that there's a nested UNION ALL whose output type
doesn't match the parent's expected type.  At the outer branch maybe
we can use NULL::bigint[] instead to be a little simpler.

SELECT NULL::int[] UNION ALL SELECT NULL::int[] UNION ALL SELECT NULL::bigint[];
ERROR:  no relation entry for relid 0

>                 if (HeapTupleIsValid(vardata.statsTuple))

This looks like the right fix to me.  We can use some comment here.

- Richard

---

From: Michael Paquier <[email-masked]>
Date: Sat, 11 Apr 2026 05:34:34 +0900

> we can use NULL::bigint[] instead to be a little simpler.

Indeed, three branches:
$ git branch --contains 9391f7152
+ REL_17_STABLE
+ REL_18_STABLE
* master
--
Michael

---

From: Tender Wang <[email-masked]>
Date: Sat, 11 Apr 2026 09:31:59 +0800

> ERROR:  no relation entry for relid 0

Yes, add it to the test case.

> This looks like the right fix to me.  We can use some comment here.

comments added.
Please see the attached patch.

-- 
Thanks,
Tender Wang

---

From: Richard Guo <[email-masked]>
Date: Sat, 11 Apr 2026 16:57:21 +0900

> Please see the attached patch.

I've pushed and back-patched the fix after some tweaks to the comment
and commit message.  I also used explain (verbose, costs off) in the
test case so that we can observe that the inner UNION ALL's output
type doesn't match the outer's.

Thanks for the report and the patch.

- Richard