Reputation: 25263
Running same query on different versions of PostgreSQL gives different result.
WITH t(a, b) AS (VALUES (1, 0))
SELECT a / b
FROM t
WHERE b <> 0;
On v11.10
I get no rows as expected fiddle
On v13.1
I get ERROR: division by zero
fiddle
Why I get division by zero for PostgreSQL v13.1
? I suppose rows should be filtered out as it done for v11.10
UPD
I think when we join, optimizer should not call lateral function sometimes (when it may) and save time:
fiddle
Upvotes: 4
Views: 119
Reputation: 44373
Newer versions of PostgreSQL (starting in 12) look through your strange use of the constant single row VALUES list to see the constant-folding opportunity. But it folds the division constant before it folds the WHERE constant, and so trips over the error.
In 11, you would still get the error in other similar places, like:
select 1/0 from pgbench_accounts where aid < -100;
This can be annoying if you are trying to come up with a very simple example not useful in its own right, but just to test something else. But I just chalk it up to "Play stupid games, win stupid prizes", and find some other way to test what I want to test. In your case, you can just make the CTE be materialized.
WITH t(a, b) AS materialized (VALUES (1, 0))
SELECT a / b
FROM t
WHERE b <> 0;
Upvotes: 4
Reputation: 222672
It looks the order of evaluation is not what one would expect it to be: that is, one would expect that 0
denominators would be filtered out by the where
clause before the computation in the select
clause happens. Obviously the database chooses to do things differently.
You can, however, easily work around this with nullif()
:
with t(a, b) as (values (1, 0))
select a / nullif(b, 0)
from t
where b <> 0;
This properly produce no rows.
I would tend qualifying this as a bug, or at least a regression. Playing around in db<>fiddle, your original code works fine in versions 9.4, 9.5, 9.6, 10 and 11, but fails in versions 12 and 13.
Upvotes: 1