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 1vxllh-00H7It-06 for pgsql-bugs@arkaria.postgresql.org; Wed, 04 Mar 2026 12:56:01 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vxllf-00ChQc-1X for pgsql-bugs@arkaria.postgresql.org; Wed, 04 Mar 2026 12:55:59 +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 1vxllf-00ChQU-0e for pgsql-bugs@lists.postgresql.org; Wed, 04 Mar 2026 12:55:59 +0000 Received: from mail-lj1-x230.google.com ([2a00:1450:4864:20::230]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1vxllc-00000000Wv1-46XQ for pgsql-bugs@lists.postgresql.org; Wed, 04 Mar 2026 12:55:59 +0000 Received: by mail-lj1-x230.google.com with SMTP id 38308e7fff4ca-38a2e62b893so7755081fa.1 for ; Wed, 04 Mar 2026 04:55:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cybertec.at; s=google; t=1772628956; x=1773233756; darn=lists.postgresql.org; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:to:from:subject:message-id:from:to:cc:subject:date :message-id:reply-to; bh=8UEj1t6hoJgBDg+yf8VHHxBGUUZIR+XcK8i1sJU4z68=; b=QVaJTvAlRdrgXabjD2mqmga9saEsoANuFlyKH/Xl9/V6tJFBvOcGKVgktukdp5gtmI MjbFLCiObOcMDE2Nz0vDBL9b3yMLF6aUoGndDZ89gk2PiAbWZSfANLxJMWJZjQOj8d4/ isQs3rRIv746YqIkD5Yfixnp++/10S+XSfOCBgImqb7G53PhvjSf57WB40awf095nIbS ZyVkJl/zcHE0/uU+NwauUiu3vr8sQg2b7pj6Va+/sO28Q1uO438RL1Y6gmzy3StbClD7 xOZDzi5dxJkvi2Gm9Cpdi9qw5UCkznX4x3A8TZ5YPVpjmTZiXsuCJc/RFFP09sBdb14d x6uw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772628956; x=1773233756; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:to:from:subject:message-id:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=8UEj1t6hoJgBDg+yf8VHHxBGUUZIR+XcK8i1sJU4z68=; b=I41aiK8+8QRQqNbLemqck181Kr+hiKXo6taJUbxSuy7FtM3LEBkr8vn120u5IE/hO6 uY+W8fU93bjwmPEP4FeZj4qQWKXYQzf6/ApPHVLvAxPxd/PES9pnSRmr8dn+aCPFNukT CtOPxiuTaltxsXcjmat3oszqW+upsZNXKuBQo4JLZcTQEdr2CRye91mBZoJMqnyC9CLI 2I56XnFCDNKob5lFWlBszYBPNhJF3DMyEzNhteswJdWM0rHptL5ZCrCv0bweqva3b3E8 kHiDvDyDPYfzUrax6IEjTB7a6wYJUPB6py89Sdbnhk9iRDxso8nQEUe1TuNfJ3NHUPu/ 1L7A== X-Forwarded-Encrypted: i=1; AJvYcCVR/pllaszIhTtKPDjBeKxLks+hsUuEIkDmNaPwrfYLpr2RTqweoih99toYP5b+Yz9DRSq4qNKmbFfQ@lists.postgresql.org X-Gm-Message-State: AOJu0YzwsU4cQQUruOcnoz4QCSfaTVVLHRvKxblBOy+TYK5xd2cTNIie 3wObAvhaXuxpDpKBjGUHNV70lAFEFm1jTpLbzYJ/T2GVduUqH40QBSQeVt7vetTSobTYS6Mc0Ru uCBH3adE= X-Gm-Gg: ATEYQzxi89xO8C4j9KlpJ6gf8orzTYD5oXLiOtZhos7OlKcZpdFrq645KUZFbvyOzEQ bA2cqlDSr6Fv5KeOk6y6GJW4tbyqiyVPdMF0pPtdY50ptCAC8izrBJx+ifZJQmk6JNT55oYgkkP wqo51VfND5fRTqecNDHUDAUnkgtr03ur71lctEA+RsP2PVovTtkpTfZOS3yCfN8RBoS1pdt6fZ7 eBqmM4xQSdLS4/dZC2UZM6ZuY2FXLXNYHh1MikyuhaAvV2KKc8+ZH8ZNCGh87wRsRClOZZsVrXS keaNkld7OYrNOO3kWxa/k0kHi2pi7letfhbuixwQbA1cNlCTH5dyGN1NsxPKnapCqqBOXC/nswx oxbACPMv7U3CRdLp8psHl83UaV2yIyg6RmXQHyDf3YjBsOvu25CpbpiW0HBrOLsQZz82hjpBLFM MFrmdOP8gY1MmfR8Lx0halkQmJaJuU28L38QZZFk9e46fE9S3oleb7 X-Received: by 2002:a05:651c:512:b0:383:1f06:559e with SMTP id 38308e7fff4ca-38a2c4ec055mr17792301fa.0.1772628956109; Wed, 04 Mar 2026 04:55:56 -0800 (PST) Received: from laurenz.albe-K4N0CV00F97414D ([88.116.133.170]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-389f2f4b2c4sm35115331fa.1.2026.03.04.04.55.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 04:55:55 -0800 (PST) Message-ID: <3242d4f3942eef5230229e22b08d4dd24ae6d19f.camel@cybertec.at> Subject: Re: GROUP BY in CTE causes ELSE in outer query to be prematurely evaluated From: Laurenz Albe To: =?ISO-8859-1?Q?Bj=F6rn?= Kautler , pgsql-bugs@lists.postgresql.org Date: Wed, 04 Mar 2026 13:55:53 +0100 In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.58.3 (3.58.3-1.fc43) MIME-Version: 1.0 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Wed, 2026-03-04 at 11:46 +0100, Bj=C3=B6rn Kautler wrote: > If you have the query >=20 > WITH FOO AS ( > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SELECT 0 AS GROUPING > =C2=A0 =C2=A0 =C2=A0) > SELECT CASE > =C2=A0 =C2=A0 WHEN GROUPING >=3D 0 THEN 'non-negative' > =C2=A0 =C2=A0 ELSE CAST((1 / 0) AS VARCHAR) > END > FROM FOO; >=20 > it works successfully, having the ELSE as a safeguard against having code= d a bug, having forgotten a WHEN branch, so it fails fast. >=20 > So if you have >=20 > WITH FOO AS ( > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SELECT -1 AS GROUPING > =C2=A0 =C2=A0 =C2=A0) > SELECT CASE > =C2=A0 =C2=A0 WHEN GROUPING >=3D 0 THEN 'non-negative' > =C2=A0 =C2=A0 ELSE CAST((1 / 0) AS VARCHAR) > END > FROM FOO; >=20 > it fails with a division by zero error. >=20 > But if you have the query >=20 > WITH FOO AS ( > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SELECT 0 AS GROUPING > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0GROUP BY 1 > =C2=A0 =C2=A0 =C2=A0) > SELECT CASE > =C2=A0 =C2=A0 WHEN GROUPING >=3D 0 THEN 'non-negative' > =C2=A0 =C2=A0 ELSE CAST((1 / 0) AS VARCHAR) > END > FROM FOO; >=20 > then it always fails with division by zero error, even though the result = should still be 'non-negative'. This is working as it should, see https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-EXPRESS= -EVAL When it is essential to force evaluation order, a CASE construct (see Sec= tion 9.18) can be used. For example, this is an untrustworthy way of trying to avoid= division by zero in a WHERE clause: SELECT ... WHERE x > 0 AND y/x > 1.5; But this is safe: SELECT ... WHERE CASE WHEN x > 0 THEN y/x > 1.5 ELSE false END; A CASE construct used in this fashion will defeat optimization attempts, = so it should only be done when necessary. (In this particular example, it would= be better to sidestep the problem by writing y > 1.5*x instead.) CASE is not a cure-all for such issues, however. One limitation of the te= chnique illustrated above is that it does not prevent early evaluation of constan= t subexpressions. As described in Section 36.7, functions and operators mar= ked IMMUTABLE can be evaluated when the query is planned rather than when it = is executed. Thus for example SELECT CASE WHEN x > 0 THEN x ELSE 1/0 END FROM tab; is likely to result in a division-by-zero failure due to the planner tryi= ng to simplify the constant subexpression, even if every row in the table has x= > 0 so that the ELSE arm would never be entered at run time. Yours, Laurenz Albe