diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index d5468edcf31..2c1daefc0c0 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -2165,6 +2165,18 @@ estimate_array_length(PlannerInfo *root, Node *arrayexpr) AttStatsSlot sslot; double nelem = 0; + /* + * Skip calling examine_variable for Var with varno 0, which has no + * valid relation entry and would error in find_base_rel. Such a Var + * can appear when a nested set operation's output type doesn't match + * the parent's expected type, because recurse_set_operations builds a + * projection target list using generate_setop_tlist with varno 0, and + * if the required type coercion involves an ArrayCoerceExpr, we can + * be called on that Var. + */ + if (IsA(arrayexpr, Var) && ((Var *) arrayexpr)->varno == 0) + return 10; /* default guess, should match scalararraysel */ + 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 0fd0e1c38b3..882b075b9a1 100644 --- a/src/test/regress/expected/union.out +++ b/src/test/regress/expected/union.out @@ -1489,3 +1489,20 @@ on true limit 1; -> Result (6 rows) +-- Test handling of Vars with varno 0 in estimate_array_length +explain (verbose, costs off) +select null::int[] union all select null::int[] union all select null::bigint[]; + QUERY PLAN +--------------------------------------------- + Append + -> Result + Output: (NULL::integer[]) + -> Append + -> Result + Output: NULL::integer[] + -> Result + Output: NULL::integer[] + -> Result + Output: NULL::bigint[] +(10 rows) + diff --git a/src/test/regress/sql/union.sql b/src/test/regress/sql/union.sql index f8826514e42..c52ca012b5c 100644 --- a/src/test/regress/sql/union.sql +++ b/src/test/regress/sql/union.sql @@ -577,3 +577,7 @@ select * from tenk1 t1 left join lateral (select t1.tenthous from tenk2 t2 union all (values(1))) on true limit 1; + +-- Test handling of Vars with varno 0 in estimate_array_length +explain (verbose, costs off) +select null::int[] union all select null::int[] union all select null::bigint[];