While working on the grouping sets patches for queries with GROUP BY
items that are constants, I noticed $subject on master. As an
example, consider
prepare q1(int) as
select $1 as c1, $1 as c2 from generate_series(1,2) t group by rollup(c1);
set plan_cache_mode to force_custom_plan;
execute q1(3);
c1 | c2
----+----
3 | 3
| 3
(2 rows)
set plan_cache_mode to force_generic_plan;
execute q1(3);
c1 | c2
----+----
3 | 3
|
(2 rows)
The reason can be seen in the plans under different modes.
-- force_custom_plan
explain (verbose, costs off) execute q1(3);
QUERY PLAN
-----------------------------------------------------
GroupAggregate
Output: (3), 3
Group Key: 3
Group Key: ()
-> Function Scan on pg_catalog.generate_series t
Output: 3
Function Call: generate_series(1, 2)
(7 rows)
-- force_generic_plan
explain (verbose, costs off) execute q1(3);
QUERY PLAN
-----------------------------------------------------
GroupAggregate
Output: ($1), ($1)
Group Key: $1
Group Key: ()
-> Function Scan on pg_catalog.generate_series t
Output: $1
Function Call: generate_series(1, 2)
(7 rows)
In custom mode, the target entry 'c2' is a Const expression, and
setrefs.c does not replace it with an OUTER_VAR, despite there happens
to be an identical Const below. As a result, when this OUTER_VAR goes
to NULL due to the grouping sets, 'c2' remains as constant 3. Look at
this code in search_indexed_tlist_for_non_var:
/*
* If it's a simple Const, replacing it with a Var is silly, even if there
* happens to be an identical Const below; a Var is more expensive to
* execute than a Const. What's more, replacing it could confuse some
* places in the executor that expect to see simple Consts for, eg,
* dropped columns.
*/
if (IsA(node, Const))
return NULL;
In generic mode, the target entry 'c2' is a Param expression, and is
replaced with the OUTER_VAR (indicated by the parentheses around the
second '$1'). So it goes to NULL when we're grouping by the set that
does not contain this Var.
Is this inconsistent behavior in different plan cache modes expected,
or does it indicate a bug that needs to be fixed?
Thanks
Richard