Hi,

On Fri, 19 Jun 2026 at 06:43, Richard Guo <[email protected]> wrote:

> 383eb21eb teaches the planner to convert "x NOT IN (SELECT ...)" to an
> anti-join when both sides of the comparison are known to be non-null.
> On the outer side we currently get that only from NOT NULL constraints
> and the outer-join-aware-Var infrastructure.
>
> That misses a case: the left-hand column has no NOT NULL constraint,
> but a qual forces it non-null anyway, as in "x IS NOT NULL AND x NOT
> IN (...)" or "x > 0 AND x NOT IN (...)".  We leave those as SubPlan
> filters today, even though x clearly can't be NULL where the NOT IN is
> evaluated.
>
> The attached patch proves the left-hand Var non-null from such a qual.
> pull_up_sublinks_jointree_recurse collects the quals at or below the
> NOT IN's jointree node (only those on rels not below the nullable side
> of an outer join, so they really do filter the rows) and hands them to
> convert_ANY_sublink_to_join, which checks them with
> find_nonnullable_vars.
>
> Quals above the NOT IN's node could help in some cases too, but that's
> a separate extension and I've left it as a follow-up.  See the details
> in the draft commit message.
>

Thanks for the patch!

I did see one issue in this here's a statement for repro:

CREATE TEMP TABLE outer_t (x int);
CREATE TEMP TABLE inner_t (y int NOT NULL);

INSERT INTO outer_t VALUES (NULL), (1);
INSERT INTO inner_t VALUES (2);

SELECT x
FROM outer_t
WHERE NOT (x = ANY('{}'::int[]))
  AND x NOT IN (SELECT y FROM inner_t);

SQL semantics return only 1. With the patch, the planner
produces a hash anti-join and also returns the NULL row: the
first qual admits it, and the anti-join preserves it, whereas the
original NOT IN evaluates to NULL and filters it out.

This helper weakness also affects the existing inner-query
proof path, but the patch creates a new regression surface.

I've posted a likely fix in [1].

Apart from the above, your patch looked good to me.

Regards,
Ayush

[1]  PostgreSQL: [PATCH] SAOP nullability analysis below NOT/BooleanTest
<https://www.postgresql.org/message-id/flat/cajtyswv3vqrjmst-gv1nsxeef-zonjvjpys910abaiumij4...@mail.gmail.com>

Reply via email to