Skip to content

fix: Fix nullability of logical InSubquery expression - #23429

Open
AdamGS wants to merge 4 commits into
apache:mainfrom
AdamGS:adamg/fix-23428
Open

fix: Fix nullability of logical InSubquery expression #23429
AdamGS wants to merge 4 commits into
apache:mainfrom
AdamGS:adamg/fix-23428

Conversation

@AdamGS

@AdamGS AdamGS commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

Report correct nullability for InSubquery logical exprs.

What changes are included in this PR?

OR the expression's and the subquery's nullability, more like ScalarSubquery.

Are these changes tested?

  1. Targeted unit tests InSubquery nullability
  2. Unit tests to verify the expression simplifier handles these queries correctly.

Are there any user-facing changes?

No

@github-actions github-actions Bot added logical-expr Logical plan and expressions optimizer Optimizer rules labels Jul 9, 2026
@AdamGS AdamGS changed the title Adamg/fix 23428 fix: Fix nullability of logical InSubquery expression Jul 9, 2026
@codecov-commenter

codecov-commenter commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.61111% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 80.91%. Comparing base (c4a539b) to head (37a5fbb).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
datafusion/expr/src/expr_schema.rs 98.11% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #23429   +/-   ##
=======================================
  Coverage   80.91%   80.91%           
=======================================
  Files        1103     1103           
  Lines      377134   377205   +71     
  Branches   377134   377205   +71     
=======================================
+ Hits       305155   305214   +59     
- Misses      53787    53793    +6     
- Partials    18192    18198    +6     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@kumarUjjawal kumarUjjawal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @AdamGS for working on this. Just had one comment for your consideration.

Comment thread datafusion/expr/src/expr_schema.rs Outdated
Expr::InSubquery(InSubquery { expr, .. }) => expr.nullable(input_schema),
Expr::InSubquery(InSubquery { expr, subquery, .. }) => {
let expr_nullable = expr.nullable(input_schema)?;
let subquery_nullable = subquery.subquery.schema().field(0).is_nullable();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we validate that the subquery has exactly one field or use checked field access and return an error here? LogicalPlanBuilder empty can create a zero-field subquery, while the current invariant only rejects more than one field.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch! I'll try and read through this and potentially change the comment on InSubquery::subquery which is why I assumed there is exactly one here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pushed a version that uses checked field access.

AdamGS added 3 commits August 5, 2026 12:50
Signed-off-by: Adam Gutglick <adamgsal@gmail.com>
Signed-off-by: Adam Gutglick <adamgsal@gmail.com>
Signed-off-by: Adam Gutglick <adamgsal@gmail.com>

@kumarUjjawal kumarUjjawal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Left two comments.

Comment thread datafusion/expr/src/expr_schema.rs Outdated
Expr::InSubquery(InSubquery { expr, subquery, .. }) => {
let expr_nullable = expr.nullable(input_schema)?;
let subquery_nullable = subquery.subquery.schema().fields().first().ok_or_else(|| {
exec_datafusion_err!("subquery must return exactly one column of data to compare against")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this return a planning error instead? The invalid subquery is detected while inspecting a logical expression, so reporting it as an execution error seems misleading.

}
}

/// A scan of `t`, whose single column `a` has the given nullability.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can add a test using LogicalPlanBuilder empty false and verify that nullable returns an error

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Signed-off-by: Adam Gutglick <adamgsal@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

logical-expr Logical plan and expressions optimizer Optimizer rules

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Logical InSubquery only take the expression nullability into account

3 participants