Thread

  1. Fix HAVING-to-WHERE pushdown with mismatched operator families

    Richard Guo <guofenglinux@gmail.com> — 2026-05-26T08:48:24Z

    Continued with the rabbit-hole around equality-relation issues, here
    is another one in the HAVING-to-WHERE pushdown path.
    
    f76686ce7 stopped the planner from pushing a HAVING clause to WHERE
    when the clause's collation disagreed with the GROUP BY's
    nondeterministic collation.  The same shape of bug exists with
    operator families: when a HAVING clause uses a comparison operator
    from a different opfamily than the GROUP BY's eqop, pushing it to
    WHERE can produce wrong results.
    
    create type t_rec as (a numeric, b int);
    create table t_having (id int, r t_rec);
    
    insert into t_having values
      (1, row(100, 1)::t_rec),
      (2, row(100.0, 1)::t_rec),
      (3, row(2, 2)::t_rec);
    
    -- wrong result: count should be 2
    select r, count(*) from t_having group by r having r *= row(100, 1)::t_rec;
        r    | count
    ---------+-------
     (100,1) |     1
    (1 row)
    
    The fix in the attached patch mirrors f76686ce7's structure.  We
    detect the conflict before flatten_group_exprs while the HAVING clause
    still contains GROUP Vars, and record the indices of unsafe clauses in
    a Bitmapset that's consulted by the existing pushdown loop.
    
    This issue can be reproduced as far back as v14.  However, the fix
    relies on RTE_GROUP to identify grouping expressions via GROUP Vars on
    pre-flatten havingQual.  As with f76686ce7, I'm inclined to back-patch
    to v18 only.
    
    Thoughts?
    
    - Richard