Re: Unsafe qual pushdown through DISTINCT with simple CASE expressions

From: "pgsql-hackers" <pgsql-hackers(at)alibaba-inc(dot)com>
To: Tender Wang <tndrwang(at)gmail(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Richard Guo <guofenglinux(at)gmail(dot)com>
Subject: Re: Unsafe qual pushdown through DISTINCT with simple CASE expressions
Date: 2026-08-18 07:05:45
Message-ID: 53911081-A871-4701-97B2-0906719D53E6@alibaba-inc.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

> On Tue, Aug 18, 2026 at 8:54 AM Tender Wang <tndrwang(at)gmail(dot)com> wrote:
> The attached patch fixes this by checking the CASE argument against
> the equality operator and input collation of each WHEN comparison
> using the existing grouping_check_operand() logic.

I confirmed that this is a real wrong-result issue, and this approach
looks correct to me.

One small issue with the patch:
+ Assert(IsA(cw->expr, OpExpr));
+ opexpr = (OpExpr *) cw->expr;

cw->expr is not guaranteed to be an OpExpr. transformCaseExpr() calls
coerce_to_boolean() after constructing the "=" expression. With a
user-defined "=" operator returning a non-boolean type and an assignment
cast from that type to boolean, cw->expr becomes a FuncExpr wrapping the
OpExpr.

Therefore, the assertion can fail in an assert build, while the cast is
unsafe in a non-assert build. I think the non-OpExpr case should be
handled conservatively as a grouping conflict.

Best Regards,
Yuhang Qiu

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Hayato Kuroda (Fujitsu) 2026-08-18 07:42:56 RE: Proposal: Conflict log history table for Logical Replication
Previous Message Alexander Lakhin 2026-08-18 07:00:01 Re: datachecksums: handle invalid and dropped databases during enable