Skip to content

ANY/IN over a subquery wrongly reported non-null #239

Description

x = ANY (subquery) and x IN (subquery) are reported non-null, but PostgreSQL returns null when the subquery yields a null row and no match is found. The generated field is non-nullable and the mapper receives null.

This is pre-existing and unrelated to GROUPING SETS. It was found while verifying #236 and is filed separately because the fix belongs to a different code path.

Repro

CREATE TABLE t (id INT PRIMARY KEY, a TEXT NOT NULL);
INSERT INTO t VALUES (1, 'x');
CREATE TABLE u (v TEXT);
INSERT INTO u VALUES ('q'), (NULL);
-- name: anyOverNullableSubquery :many
SELECT a = ANY (SELECT v FROM u) FROM t;

Norm reports notNull = true. PostgreSQL returns null:

 ?column?
----------

(1 row)

Three-valued logic: 'x' = 'q' is false, 'x' = NULL is unknown, so the ANY result is unknown rather than false.

Cause

NodeTreeNullabilityAnalyzer's SubLink branch treats ANY_SUBLINK and EXISTS_SUBLINK alike. EXISTS is genuinely never null; ANY/IN over a subquery is not. The subquery body is also absent from the parsed SubLink node (only subLinkType and outerOperand are retained), so the analyzer cannot see the inner column's nullability even in principle without extending the parser.

Note x = ANY (array) is a ScalarArrayOpExpr, a different node, and is not implicated here.

Affected versions

PostgreSQL 16, 17 and 18 — verified identical on all three.

Verified at

Commit 58f9029, before the #236 work. The SubLink branch is byte-identical at that commit, so this is not a regression from it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions