mirror of
https://github.com/postgres/postgres.git
synced 2026-04-12 12:36:49 -04:00
Fix estimate_array_length error with set-operation array coercions
When a nested set operation's output type doesn't match the parent's
expected type, recurse_set_operations builds a projection target list
using generate_setop_tlist with varno 0. If the required type
coercion involves an ArrayCoerceExpr, estimate_array_length could be
called on such a Var, and would pass it to examine_variable, which
errors in find_base_rel because varno 0 has no valid relation entry.
Fix by skipping the statistics lookup for Vars with varno 0.
Bug introduced by commit 9391f7152. Back-patch to v17, where
estimate_array_length was taught to use statistics.
Reported-by: Justin Pryzby <pryzby@telsasoft.com>
Author: Tender Wang <tndrwang@gmail.com>
Reviewed-by: Richard Guo <guofenglinux@gmail.com>
Discussion: https://postgr.es/m/adjW8rfPDkplC7lF@pryzbyj2023
Backpatch-through: 17
This commit is contained in:
parent
c05c3baf16
commit
93ed187201
3 changed files with 33 additions and 0 deletions
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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[];
|
||||
|
|
|
|||
Loading…
Reference in a new issue