## Description This issue concerns the identity `NOT NOT P = P`, which is valid under SQL three-valued logic because double negation preserves TRUE, FALSE, and NULL. When `P` is an `IN` subquery, PostgreSQL chooses different plans for the equivalent forms.
### Expected Behaviour PostgreSQL should remove double negation before subquery planning and produce the same semijoin plan as the unwrapped `IN` predicate. ### Actual Behaviour The plain predicate is pulled up into a `Hash Semi Join`. The double-negated form remains a hashed `SubPlan` evaluated by an outer sequential scan. In the standalone case, execution time increases from 7.143 ms to 12.321 ms, approximately 1.72x. Generated pair 3137 exhibits a larger order-stable instance: median execution time increases from 2.255 ms to 404.978 ms, approximately 178.6x. ## How to repeat ```sql DROP TABLE IF EXISTS identity_outer; DROP TABLE IF EXISTS identity_inner; CREATE TABLE identity_outer (v INTEGER NOT NULL); CREATE TABLE identity_inner (v INTEGER NOT NULL); INSERT INTO identity_outer SELECT g FROM generate_series(90001, 91000) AS g; INSERT INTO identity_inner SELECT g FROM generate_series(1, 100000) AS g; ANALYZE identity_outer; ANALYZE identity_inner; -- Original form P. EXPLAIN (ANALYZE, BUFFERS, VERBOSE, SETTINGS, TIMING OFF) SELECT COUNT(*) FROM identity_outer AS o WHERE o.v IN ( SELECT i.v FROM identity_inner AS i ); -- Equivalent double-negated form NOT NOT P. EXPLAIN (ANALYZE, BUFFERS, VERBOSE, SETTINGS, TIMING OFF) SELECT COUNT(*) FROM identity_outer AS o WHERE NOT NOT ( o.v IN (SELECT i.v FROM identity_inner AS i) ); ``` Both queries return 1,000. Characteristic plans and measured times are: ```text P: Hash Semi Join Execution Time: 7.143 ms NOT NOT P: Seq Scan on identity_outer Filter: ANY (... hashed SubPlan 1 ...) Execution Time: 12.321 ms ```
