jayzhan211 commented on PR #25338:
URL: https://github.com/apache/datafusion/pull/25338#issuecomment-5697075935

   Thanks @adriangb , here is a suggestion:
   
   **Correlated `NOT IN` with a scalar-function key now fails to plan**
   
   The `LeftAnti` branch now reads nullability from the key expressions. Most 
scalar UDFs use the default `return_field_from_args`, which always says the 
result can be NULL (`datafusion/expr/src/udf.rs`). So a key like `upper(s)` 
over a `NOT NULL` column now turns on `null_aware`.
   
   For a correlated `NOT IN` in `WHERE`, that join has 2+ keys (value + 
correlation). `HashJoinExec` rejects null-aware `LeftAnti` with more than one 
key, and null-aware joins can't fall back to a sort-merge join:
   
   ```sql
   CREATE TABLE t1(k INT NOT NULL, s VARCHAR NOT NULL) AS VALUES (1, 'a');
   CREATE TABLE t2(k INT NOT NULL, s VARCHAR NOT NULL) AS VALUES (1, 'B');
   SELECT * FROM t1 WHERE upper(t1.s) NOT IN (SELECT t2.s FROM t2 WHERE t2.k = 
t1.k);
   -- main: plans a plain LeftAnti and returns (1, 'a')
   -- this PR: expected "null_aware LeftAnti joins only support single column 
join key"
   ```
   
   Nullable columns already fail like this on main (#25347), but this change 
extends the failure to common function keys over non-nullable data. It also 
pins uncorrelated `lower(s) NOT IN (...)` over `NOT NULL` columns to a 
`CollectLeft` null-aware join for no correctness gain.
   
   Suggest limiting the expression-level check on the `LeftAnti` path to the 
single-key case until #25347 is fixed:
   
   ```diff
        let null_aware = if join_type == JoinType::LeftAnti && 
in_predicate_opt.is_some() {
            let (equijoin_keys, residual_filter) = 
split_eq_and_noneq_join_predicate(
                join_filter.clone(),
                left.schema(),
                sub_query_alias.schema(),
            )?;
   -        join_keys_may_be_null(
   -            &equijoin_keys,
   -            residual_filter.as_ref(),
   -            left.schema(),
   -            sub_query_alias.schema(),
   -        )?
   +        if equijoin_keys.len() == 1 {
   +            join_keys_may_be_null(
   +                &equijoin_keys,
   +                residual_filter.as_ref(),
   +                left.schema(),
   +                sub_query_alias.schema(),
   +            )?
   +        } else {
   +            // Null-aware LeftAnti supports a single key only (#25347); 
keep the
   +            // previous column-based test so correlated NOT IN still plans.
   +            join_filter_columns_may_be_null(&join_filter, left.schema(), 
sub_query_alias.schema())?
   +        }
        } else {
   ```
   
   Please also add an slt case with the correlated query above.


-- 
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