Re: Fix HAVING-to-WHERE pushdown with nondeterministic collations

Richard Guo <guofenglinux@gmail.com>

From: Richard Guo <guofenglinux@gmail.com>
To: SATYANARAYANA NARLAPURAM <satyanarlapuram@gmail.com>
Cc: wenhui qiu <qiuwenhuifx@gmail.com>, Pg Hackers <pgsql-hackers@lists.postgresql.org>
Date: 2026-05-08T08:07:07Z
Lists: pgsql-hackers
On Wed, May 6, 2026 at 9:58 AM SATYANARAYANA NARLAPURAM
<satyanarlapuram@gmail.com> wrote:
> It appears HAVING-to-WHERE pushdown is still wrong with CASE and nondeterministic
> collations. The shorthand CASE expression bypasses the new collation-conflict detector,
> so the HAVING clause gets pushed to WHERE, filtering rows before
> grouping and silently changing aggregate results.

Right.  For simple CASE (CaseExpr with a non-NULL arg), parse analysis
builds each WHEN as OpExpr(CaseTestExpr op val), where CaseTestExpr is
a placeholder for the arg, while the actual arg sits at cexpr->arg,
outside the OpExpr that carries the comparison's inputcollid.  A GROUP
Var at cexpr->arg is therefore visited without the WHEN's inputcollid
on the stack.  So the conflict fails to be detected, and the HAVING
clause is incorrectly pushed to WHERE.

> My understanding is shallow here, attached a draft patch that adds a CaseExpr branch to
> having_collation_conflict_walker() mirroring the existing RowCompareExpr
> special case. Patch includes the tests. Please take a look.

This patch is on the right track.  I didn't like how the stack was
restored after walking cexpr->arg; list_truncate fits better there.
The comments also needed some tightening.  I've made those
adjustments, pushed, and back-patched.

- Richard