public inbox for [email protected]  
help / color / mirror / Atom feed
From: Tender Wang <[email protected]>
To: Richard Guo <[email protected]>
Cc: Justin Pryzby <[email protected]>
Cc: [email protected]
Cc: Paul Jungwirth <[email protected]>
Cc: Tom Lane <[email protected]>
Cc: Michael Paquier <[email protected]>
Subject: Re: pg17: XX000: no relation entry for relid 0
Date: Sat, 11 Apr 2026 09:31:59 +0800
Message-ID: <CAHewXNkBL9rh1SqVArtchK3mwq3BXyTk7sArZgQJBnqhQZ=TCw@mail.gmail.com> (raw)
In-Reply-To: <CAMbWs49Wi81GGO_drC4PJgQUehz4_+ekmxHyO9nvLzP1-mJuCw@mail.gmail.com>
References: <adjW8rfPDkplC7lF@pryzbyj2023>
	<CAHewXN=_C3apEh4nDndgbOiYnFAYDDuMWAozPP0G3iL=7zQbJg@mail.gmail.com>
	<CAMbWs49Wi81GGO_drC4PJgQUehz4_+ekmxHyO9nvLzP1-mJuCw@mail.gmail.com>

Richard Guo <[email protected]> 于2026年4月10日周五 22:39写道:
>
> On Fri, Apr 10, 2026 at 9:49 PM Tender Wang <[email protected]> wrote:
> > Justin Pryzby <[email protected]> 于2026年4月10日周五 18:54写道:
> > > 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
>
> 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

Yes, add it to the test case.

>
> > 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?
>
> This looks like the right fix to me.  We can use some comment here.

comments added.
Please see the attached patch.

-- 
Thanks,
Tender Wang


Attachments:

  [application/octet-stream] 0001-Fix-no-relation-entry-for-relid-0-in-nested-UNION-AL.patch (2.8K, 2-0001-Fix-no-relation-entry-for-relid-0-in-nested-UNION-AL.patch)
  download | inline diff:
From 09cae95e24996e34ca12e38133150e71e351edcc Mon Sep 17 00:00:00 2001
From: Tender Wang <[email protected]>
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



view thread (6+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
  Subject: Re: pg17: XX000: no relation entry for relid 0
  In-Reply-To: <CAHewXNkBL9rh1SqVArtchK3mwq3BXyTk7sArZgQJBnqhQZ=TCw@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox