fornwall opened a new pull request, #24516:
URL: https://github.com/apache/datafusion/pull/24516

   ## Which issue does this PR close?
   
   - Closes apache/datafusion#24513.
   
   ## Rationale for this change
   
   A scalar subquery that returns zero rows evaluates to `NULL`, even when its 
projected expression is non-nullable. DataFusion currently derives 
`Expr::ScalarSubquery` nullability from the subquery's output field. This can 
produce a non-nullable output schema containing `NULL`, and can cause 
`SimplifyExpressions` to incorrectly fold predicates such as:
   
   ```sql
   SELECT (SELECT 1 WHERE FALSE) IS NULL;
   ```
   
   to `false`.
   
   This change deliberately marks all scalar subqueries nullable, including 
those guaranteed to return exactly one row (such as an ungrouped aggregate like 
`(SELECT count(*) FROM t)`). This is a conservative trade-off that gives up 
some nullability precision for correctness, and is consistent with how 
PostgreSQL treats scalar subqueries.
   
   A possible follow-up refinement is a `LogicalPlan::min_rows()` lower bound 
(mirroring the existing `max_rows()`), which would let uncorrelated scalar 
subqueries provably returning at least one row keep their projected field's 
nullability.
   
   ## What changes are included in this PR?
   
   Scalar subqueries are conservatively marked nullable in logical expression 
schema derivation and physical expression planning. The projected field's data 
type, name, and metadata are preserved.
   
   ## Are these changes tested?
   
   Yes. Unit tests cover logical schema derivation and expression 
simplification, and SQLLogicTests cover both zero-row execution and `IS NULL` 
correctness.
   
   The full workspace test suite and Clippy with warnings denied pass.
   
   ## Are there any user-facing changes?
   
   Yes. Zero-row scalar subqueries with non-nullable projections now return 
`NULL` without a schema validation error, and `IS NULL` predicates produce the 
correct result.
   
   In addition, output schemas containing scalar subqueries now always mark 
those fields as nullable, even for subqueries that can never produce `NULL`. 
Downstream consumers that inspect schema nullability can observe this change. 
No public APIs change.
   
   ---
   
   AI usage: Created with Claude Code and Opus 5. I have reviewed the code and 
made modifications where it made sense.


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