Re: Fix HAVING-to-WHERE pushdown with mismatched operator families
Florin Irion <irionr@gmail.com>
From: Florin Irion <irionr@gmail.com>
To: Richard Guo <guofenglinux@gmail.com>
Cc: pgsql-hackers@lists.postgresql.org
Date: 2026-06-19T12:10:26Z
Lists: pgsql-hackers
Il giorno ven 19 giu 2026 alle ore 08:43 Richard Guo <guofenglinux@gmail.com>
ha scritto:
> On Fri, Jun 19, 2026 at 12:34 AM Florin Irion <irionr@gmail.com> wrote:
> > When an outer qual is pushed into a GROUP BY subquery it lands in
> havingQual (correct), but find_having_conflicts then misses the conflict
> because the pushed qual carries base-table Vars, not GROUP Vars — so the
> clause gets silently moved to WHERE, filtering before aggregation.
>
> I don't think so. The pushed qual carries the GROUP Vars, not the
> base-table Vars.
>
> > Reproducer:
> > ```
> > CREATE TYPE t_rec AS (x numeric);
> > CREATE TABLE t_grp (a t_rec);
> > INSERT INTO t_grp VALUES (ROW(1.0)), (ROW(1.00)), (ROW(2));
> >
> > -- record_ops (default) considers 1.0 and 1.00 equal; record_image_ops
> does not.
> > -- Expected: one row (1.0), count = 2
> > -- Got: one row (1.0), count = 1 (wrong)
> > SELECT * FROM (SELECT a, count(*) FROM t_grp GROUP BY a) s
> > WHERE a *= ROW(1.0)::t_rec;
> > ```
>
> I ran your reproducer, and I got the Expected result:
>
> SELECT * FROM (SELECT a, count(*) FROM t_grp GROUP BY a) s
> WHERE a *= ROW(1.0)::t_rec;
> a | count
> -------+-------
> (1.0) | 2
> (1 row)
>
> Curious how you got the wrong result with this patch.
>
> > EXPLAIN shows the *= filter pushed inside the aggregate scan rather than
> sitting above it as a Subquery Scan filter.
>
> Here is the EXPLAIN I got:
>
> EXPLAIN (COSTS OFF)
> SELECT * FROM (SELECT a, count(*) FROM t_grp GROUP BY a) s
> WHERE a *= ROW(1.0)::t_rec;
> QUERY PLAN
> ---------------------------------------
> HashAggregate
> Group Key: t_grp.a
> Filter: (t_grp.a *= '(1.0)'::t_rec)
> -> Seq Scan on t_grp
> (4 rows)
>
> So the filter stays in HAVING instead of being pushed to Scan, which
> is expected. I wonder how you get a plan with the filter being pushed
> to scan. Can you show your output of EXPLAIN?
>
> - Richard
>
Huh, I'm not able to reproduce it anymore either,
probably while reviewing it, I played a bit with some things and this test
was using some bogus install.
Sorry for the noise.
Cheers,
Florin
--
* Florin Irion *
* https://www.enterprisedb.com <https://www.enterprisedb.com/>*