Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w0fAB-0026MU-07 for pgsql-bugs@arkaria.postgresql.org; Thu, 12 Mar 2026 12:29:15 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w0fA9-00EmHY-1M for pgsql-bugs@arkaria.postgresql.org; Thu, 12 Mar 2026 12:29:13 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w0cQn-00E2nW-0e for pgsql-bugs@lists.postgresql.org; Thu, 12 Mar 2026 09:34:13 +0000 Received: from sigil.arcsin.de ([2a03:4000:2:cd1:0:8a5f:404d:8ee5]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1w0cQl-00000002HJE-0F8K for pgsql-bugs@lists.postgresql.org; Thu, 12 Mar 2026 09:34:13 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=arcsin.de; h= in-reply-to:from:from:content-language:references:subject :subject:mime-version:date:date:message-id:content-type :content-type:x-amavis-category; s=dkim02; t=1773308045; x= 1775122446; bh=thvlgmirTIzuMo74nLM2uBTln2NuTxe9RLdYhyu9+C0=; b=n 3xwKl6h2d8NutD5GtJDSlKSYiRXNQ03CD+RZslAxfn9uItmfh2KrZg0l2R4XQbZ2 f4HsBhQkGWc/bHY4TdYgAPSatTSlz7V+rHm849Rj1CnsvtXwFLQCPC95GWPUZD2F QlkY7I/Uz4Vf190+RiQY6sldj1Z88441cY1N2gKat9YkUeEEUR5d+YNO53Pli340 E4Ed2IpqfJWcQBWZofjBkA1U+ipWo8CJLZvgwe6Lopax9fS8UdwjU/oCIaUPC+4B 13OFlti8WuzvU0vDPRN2c8VrA78nxMRXRkYpB5B1I8HFLPniFLJG/4HTutth6lwT V0baxEpoYfG45yIAhpZrQ== X-Amavis-Category: sigil.arcsin.de; category=Clean Content-Type: multipart/alternative; boundary="------------xDOoqzgnSxnzZ9WYV0H8m4Gz" Message-ID: Date: Thu, 12 Mar 2026 10:34:04 +0100 MIME-Version: 1.0 Subject: Re: BUG #19428: Lazy evaluation of type checking in CASE in SQL functions including subqueries no longer works in 18 To: pgsql-bugs@lists.postgresql.org References: <19428-d9ac6c4d84c0bc81@postgresql.org> <3708.1773251497@sss.pgh.pa.us> Content-Language: en-US From: Damian Lukowski Autocrypt: addr=damian.lukowski@credativ.de; keydata= xjMEZ7c2uhYJKwYBBAHaRw8BAQdAceF3EJt2itpxKWUTR6jMvERlO9hfxBqDZ8iTixrhykvN LURhbWlhbiBMdWtvd3NraSA8ZGFtaWFuLmx1a293c2tpQGNyZWRhdGl2LmRlPsKQBBMWCAA4 AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAFiEEn2yM4tn2T3ZoWMszfF3Rm/We5T4FAme3 NxQACgkQfF3Rm/We5T4yBQEAx1pLzviFfdx54XAP5RcEw0cQd3bSWYZbTFPDR1OPxBMA/icc vL1ZKvpmMpsSp8zwtRjRtVBd4g+t/rcGzagVVE0OzjgEZ7c2uhIKKwYBBAGXVQEFAQEHQKe8 LrdoRxv2hpm8b6OqN3iWnI4b4lymHJNc2Q+g6p9JAwEIB8J4BBgWCAAgAhsMFiEEn2yM4tn2 T3ZoWMszfF3Rm/We5T4FAme3NuoACgkQfF3Rm/We5T4SlgEA9jbDVIs9Zhw4O2d9+FIF6Unm nlZRw1p+8UADGtpM5u4BAPEe8Y5UBIdqkf+4Ujx18w4LCcmMV8RfPyAGIPbTG04D In-Reply-To: <3708.1773251497@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk This is a multi-part message in MIME format. --------------xDOoqzgnSxnzZ9WYV0H8m4Gz Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit >> A colleague has complained to me that the following (minimal reproducer he >> could come up with) worked on pre-18, but no longer does on 18: >> ... >> SELECT CASE >> WHEN selector IS NULL THEN $1::text >> ELSE $1::inet::text >> END >> ... >> I bisected this to 0dca5d68d7b. Looks like they depend on lazy evaluation in >> CASE via the subquery to check if the second argument is a valid inet, which >> no longer works after 0dca5d68d7b. Is that an intended change? > We have never promised to avoid constant-folding within the > subexpressions of a CASE [1]. So it was pure accident that > this example worked before, and I don't think it's a bug that > it doesn't work now. For a better understanding, which one is the constant that is being folded? I have found several articles explaining constant folding but their examples are obvious, e.g. `7 + 1` can be folded to `8` [1, 2], or `1 = 1` can be folded to `TRUE` [3]. However, I have not found any articles that resemble this case. Aren't `arg` and `$1` variables? Where is the boundary between constants and non-constants? [1] https://www.cybertec-postgresql.com/en/how-the-postgresql-query-optimizer-works/ [2] https://www.oreilly.com/library/view/mastering-postgresql-12/9781838988821/b44dc21f-cefa-464a-82e1-391b84fc9f40.xhtml [3] https://medium.com/@ukhore/deep-dive-postgresql-query-execution-mechanisms-777a79d8caf0 --------------xDOoqzgnSxnzZ9WYV0H8m4Gz Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 7bit
A colleague has complained to me that the following (minimal reproducer he
could come up with) worked on pre-18, but no longer does on 18:
...
SELECT CASE
    WHEN selector IS NULL THEN $1::text
    ELSE $1::inet::text
END
...
I bisected this to 0dca5d68d7b. Looks like they depend on lazy evaluation in
CASE via the subquery to check if the second argument is a valid inet, which
no longer works after 0dca5d68d7b. Is that an intended change?
We have never promised to avoid constant-folding within the
subexpressions of a CASE [1].  So it was pure accident that
this example worked before, and I don't think it's a bug that
it doesn't work now.

For a better understanding, which one is the constant that is being folded? I have found several articles explaining constant folding but their examples are obvious, e.g. `7 + 1` can be folded to `8` [1, 2], or `1 = 1` can be folded to `TRUE` [3].

However, I have not found any articles that resemble this case. Aren't `arg` and `$1` variables? Where is the boundary between constants and non-constants?

[1] https://www.cybertec-postgresql.com/en/how-the-postgresql-query-optimizer-works/
[2] https://www.oreilly.com/library/view/mastering-postgresql-12/9781838988821/b44dc21f-cefa-464a-82e1-391b84fc9f40.xhtml
[3] https://medium.com/@ukhore/deep-dive-postgresql-query-execution-mechanisms-777a79d8caf0

--------------xDOoqzgnSxnzZ9WYV0H8m4Gz--