Re: BUG #19037: Planner fails on estimating array length with "no relation entry" error

Tom Lane <tgl@sss.pgh.pa.us>

From: Tom Lane <tgl@sss.pgh.pa.us>
To: exclusion@gmail.com
Cc: pgsql-bugs@lists.postgresql.org
Date: 2025-08-30T21:51:16Z
Lists: pgsql-bugs

Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Fix planner error when estimating SubPlan cost

Attachments

PG Bug reporting form <noreply@postgresql.org> writes:
> The following script:
> create table t(ia int[]);
> select exists (select 1 from (select 1) where case when b then 1 else 0 end
> = 1)
>   from (select 1 = any(ia) as b from t);
> triggers:
> ERROR:  XX000: no relation entry for relid 2
> LOCATION:  find_base_rel, relnode.c:426

Thanks for the report.  After a bit of experimentation, I can shorten
the reproducer to

select exists (select 1 where (1 = any(ia))::int = 1) from t;
ERROR:  no relation entry for relid 1

but it doesn't happen any more if you simplify further to

select exists (select 1 where 1 = any(ia)) from t;

The reason for the difference seems to be that make_subplan
checks to see if the EXISTS can be converted to a hashable ANY
subplan (cf. convert_EXISTS_to_ANY), and the form where there's
a top-level "=" operator in the sub-select's WHERE clause can
be so converted.  Then we hit the failure while trying to do
cost_qual_eval on the converted ANY expression.  So you also
get this failure if you manually write out the form that
convert_EXISTS_to_ANY is generating:

select ((1 = any(ia))::int) = any (select 1) from t;
ERROR:  no relation entry for relid 1

Anyway that's sort of a sideshow.  The real issue here is that
we're applying cost_qual_eval before the planner has created
any RelOptInfos, which means that examine_variable won't work.
I find it surprising that this is the first report of such trouble,
because it certainly isn't obvious that cost_qual_eval shouldn't
be allowed to consult statistics.

The most expedient solution is probably to hack examine_variable
so that it doesn't fail if root->simple_rel_array isn't there yet.
That seems mighty ugly though.

Another low-risk response could be to revert 9391f7152.  But I don't
care for that because it's not really addressing the underlying
problem.  We might have the same issue elsewhere in cost estimation
already, and even if we don't, it would be quite likely we'd introduce
it again in future.

In some sense the "right" fix would be to do SubPlan generation
later, when we have statistics available for the Vars of the
parent query.  But that seems like a rather large task, and
we'd surely not wish to back-patch the results.

So I'm not really seeing another workable answer besides hacking
examine_variable, more or less as attached.

			regards, tom lane