adriangb commented on issue #25347:
URL: https://github.com/apache/datafusion/issues/25347#issuecomment-5689471249

   Most of this is already covered by the two open PRs. I measured the 18-shape 
matrix at each stage; what is left is one small gap.
   
   ## Where the matrix stands
   
   #25339 fixes **every column-value shape**, A2/A4/A6 and their B and C 
counterparts included. With #25348 on top of it, the shapes still wrong are 
exactly the six with a **constant value and a correlated subquery**:
   
   | # | Query | Correct | With #25339 + #25348 |
   |---|---|---|---|
   | A3 | `WHERE 3 NOT IN (... WHERE t_in.g = t_out.g)` | `1` | `1, 2` ❌ |
   | A5 | `WHERE 3 NOT IN (... WHERE t_in.g > t_out.g)` | `2` | **error** ❌ |
   | B3 | `... OR g = 99`, equality correlation | `1` | `1, 2` ❌ |
   | B5 | `... OR g = 99`, non-equality correlation | `2` | **error** ❌ |
   | C3 | `(...) IS NULL`, equality correlation | `2` | *(none)* ❌ |
   | C5 | `(...) IS NULL`, non-equality correlation | `1` | **error** ❌ |
   
   The errors are:
   
   ```
   Error during planning: null_aware LeftAnti join requires equi-join keys, but 
the join has none
   Error during planning: null_aware LeftMark join requires equi-join keys, but 
the join has none
   ```
   
   The other twelve shapes are correct at that point. So this issue reduces to 
part 2 of the plan above — the constant value — and parts 1 and 3 are handled 
by #25339.
   
   ## Root cause of the remaining six
   
   A constant value expression holds no column reference, so `3 = sq.id` is not 
a valid equi-join key and cannot serve as the null-aware join's value 
comparison.
   
   For an **uncorrelated** subquery that left the join with no key at all, 
which is what #25348 fixes by projecting the constant as a column of the outer 
side. For a **correlated** subquery it is worse: the correlation supplies the 
only equi-join key, so the join compares `grp` and never compares the value at 
all, while still reporting itself null-aware.
   
   ## The fix
   
   Extend the projection #25348 already performs to the correlated case: keep 
the correlation predicate aside, rebuild the `IN` equality against the 
projected column, then restore the correlation as a separate conjunct. The join 
then has the value comparison as one key and the correlation as the other:
   
   ```
   LeftAnti Join: __correlated_sq_1_value = __correlated_sq_1.id
                  AND outer_t.grp = __correlated_sq_1.grp null_aware
     Projection: outer_t.id, outer_t.grp, Int32(3) AS __correlated_sq_1_value
       TableScan: outer_t
     SubqueryAlias: __correlated_sq_1
       ...
   ```
   
   Multiple keys and a residual filter are both carried by the null-aware join 
itself after #25339, so no shape needs a fallback and the plan stays a **single 
join** — no three-valued decomposition, no extra scans of the subquery.
   
   With this applied, all **18 of 18** shapes match DuckDB 1.5.2 and PostgreSQL 
17.11.
   
   ## Status
   
   The change is 44 lines in `decorrelate_predicate_subquery.rs` plus tests, 
and a new `correlated_not_in.slt` covering the full matrix from this issue. 
Verified on `#25339 + #25348 + this commit`:
   
   | check | result |
   |---|---|
   | matrix | 18/18 correct |
   | full `sqllogictest` suite | pass, 521 files |
   | `datafusion-optimizer` unit tests | 853 pass |
   | `cargo fmt --all` / `cargo clippy` | clean |
   
   It depends on both #25339 and #25348 being in history, so rather than post a 
three-PR stack I will open the PR once those two merge. The patch is attached 
here in the meantime.
   
   ---
   _Generated by [Claude Code](https://claude.ai/code)_
   
   
   
[25347-constant-correlated-not-in.patch](https://github.com/user-attachments/files/32264856/25347-constant-correlated-not-in.patch)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to