BUG #19401: Inconsistent predicate evaluation with derived table vs direct query involving NULL

Started by PG Bug reporting form2 months ago2 messagesbugs
Jump to latest
#1PG Bug reporting form
noreply@postgresql.org

The following bug has been logged on the website:

Bug reference: 19401
Logged by: Ce Lyu
Email address: 2530254482@qq.com
PostgreSQL version: 18.1
Operating system: Ubuntu
Description:

Dear PostgreSQL developers,

I would like to report a behavior that appears to be incorrect and
inconsistent in PostgreSQL when the same predicate is evaluated in (1) a
derived table and (2) a direct query.

The two queries are logically equivalent, but they return different
cardinalities.

Environment

PostgreSQL version:
PostgreSQL 18.1 (Debian 18.1-1.pgdg13+2) on x86_64-pc-linux-gnu, compiled by
gcc (Debian 14.2.0-19) 14.2.0, 64-bit

Minimal Reproduction

CREATE TABLE t0 (c0 TEXT);
INSERT INTO t0 (c0) VALUES ('4');
-- result: length 0;
SELECT ref0 FROM (SELECT (any_value(c0)) AS ref0, ((('j' = NULL) <= (NULL =
NULL))) AS ref1 FROM t0) AS s WHERE ref1;
-- result: length 1; (NULL)
SELECT (any_value(c0)) FROM t0 WHERE (('j' = NULL) <= (NULL = NULL));

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: PG Bug reporting form (#1)
Re: BUG #19401: Inconsistent predicate evaluation with derived table vs direct query involving NULL

PG Bug reporting form <noreply@postgresql.org> writes:

I would like to report a behavior that appears to be incorrect and
inconsistent in PostgreSQL when the same predicate is evaluated in (1) a
derived table and (2) a direct query.

The two queries are logically equivalent, but they return different
cardinalities.

CREATE TABLE t0 (c0 TEXT);
INSERT INTO t0 (c0) VALUES ('4');
-- result: length 0;
SELECT ref0 FROM (SELECT (any_value(c0)) AS ref0, ((('j' = NULL) <= (NULL =
NULL))) AS ref1 FROM t0) AS s WHERE ref1;
-- result: length 1; (NULL)
SELECT (any_value(c0)) FROM t0 WHERE (('j' = NULL) <= (NULL = NULL));

These are not "logically equivalent". The first one applies the
WHERE filter above the aggregation, the second one applies it
before the aggregation. An aggregate will produce some value
(typically NULL) even if there are zero input rows, so the second
query gives a single NULL result as-expected. In the first query,
the subselect produces a row (4,NULL) but then the outer WHERE
filters that row away.

regards, tom lane