Wrong results: WHERE on inheritance parent column drops all rows when cross-joined with a distributed table through LEFT JOIN ... ON FALSE
Summary
When a regular table that has an inheritance child is cross-joined with a distributed table and combined with LEFT JOIN ... ON FALSE, a WHERE predicate on a column of the inheritance parent always evaluates to false on the worker, so the query returns zero rows.
Versions affected
- Citus 13.0 (
citusdata/citus:13.0-pg16)
- Citus 14.0 (
citusdata/citus:postgres_17)
- Citus nightly — extension 15.0-1 on PostgreSQL 18.1
Vanilla PostgreSQL 17 (clean postgres:17 image, shared_preload_libraries empty, citus extension not installed) returns the correct answer.
Repro
CREATE TABLE t0(c0 REAL);
CREATE TABLE t1() INHERITS(t0);
CREATE TABLE t3(c0 REAL);
SELECT create_distributed_table('t3', 'c0');
INSERT INTO t1(c0) VALUES (0.5);
INSERT INTO t3(c0) VALUES (1);
SELECT 1 FROM t3, t0 LEFT JOIN t1 ON FALSE; -- returns 1 (correct)
SELECT 1 FROM t3, t0 LEFT JOIN t1 ON FALSE WHERE t0.c0 IS NOT NULL; -- returns 0 (expected: 1)
SELECT 1 FROM t3, t0 LEFT JOIN t1 ON FALSE WHERE TRUE; -- returns 1 (correct)
t0.c0 is 0.5 (inherited from t1), so the second query should return one row.
Diagnosis
EXPLAIN (ANALYZE, VERBOSE) of the failing query shows the worker SQL Citus emits:
SELECT 1
FROM (SELECT NULL::real AS c0 WHERE false) t3(c0),
( (SELECT NULL::real AS c0
FROM (SELECT intermediate_result."dummy-1"
FROM read_intermediate_result('1_1','binary')
intermediate_result("dummy-1" integer)) t0_1) t0
LEFT JOIN
(SELECT NULL::real AS c0
FROM (SELECT intermediate_result."dummy-1"
FROM read_intermediate_result('1_2','binary')
intermediate_result("dummy-1" integer)) t1_1) t1
ON (false) )
WHERE (t0.c0 IS NOT NULL)
-> Result One-Time Filter: false
t0.c0 is rewritten to a literal NULL::real, so WHERE (NULL IS NOT NULL) constant-folds to false. The real values are pulled into intermediate_result but stay buried in the inner sub-select that nothing references.
Trigger conditions (each removal makes the bug disappear): inheritance child of t0, the cross-joined t3 being distributed, the LEFT JOIN ... ON FALSE, and a WHERE referencing the inheritance parent's column.
This bug was analyzed with the help of Claude.
Wrong results: WHERE on inheritance parent column drops all rows when cross-joined with a distributed table through
LEFT JOIN ... ON FALSESummary
When a regular table that has an inheritance child is cross-joined with a distributed table and combined with
LEFT JOIN ... ON FALSE, aWHEREpredicate on a column of the inheritance parent always evaluates to false on the worker, so the query returns zero rows.Versions affected
citusdata/citus:13.0-pg16)citusdata/citus:postgres_17)Vanilla PostgreSQL 17 (clean
postgres:17image,shared_preload_librariesempty,citusextension not installed) returns the correct answer.Repro
t0.c0is0.5(inherited fromt1), so the second query should return one row.Diagnosis
EXPLAIN (ANALYZE, VERBOSE)of the failing query shows the worker SQL Citus emits:t0.c0is rewritten to a literalNULL::real, soWHERE (NULL IS NOT NULL)constant-folds tofalse. The real values are pulled intointermediate_resultbut stay buried in the inner sub-select that nothing references.Trigger conditions (each removal makes the bug disappear): inheritance child of
t0, the cross-joinedt3being distributed, theLEFT JOIN ... ON FALSE, and aWHEREreferencing the inheritance parent's column.This bug was analyzed with the help of Claude.