Visitar URL original
API: Handle null partition values in startsWith residuals by LuciferYang · Pull Request #18414 · apache/iceberg · GitHub
Skip to content

API: Handle null partition values in startsWith residuals - #18414

Open
LuciferYang wants to merge 3 commits into
apache:mainfrom
LuciferYang:fix/api-residual-startswith-null
Open

LuciferYang wants to merge 3 commits into
apache:mainfrom
LuciferYang:fix/api-residual-startswith-null

Conversation

@LuciferYang

Copy link
Copy Markdown

Closes #18412.

ResidualVisitor.startsWith and notStartsWith call startsWith on the partition value without a null check, so the residual for a null partition throws NullPointerException. ManifestFilterManager computes a residual for each live file in a manifest it rewrites, so deleteFromRowFilter(startsWith("s", "a")) on an identity(s) table fails whenever that manifest also holds a file with a null partition value. Scans hit it with filters like or(isNull(s), startsWith(s, "a")): the null-partition task survives planning through isNull, and FileScanTask.residual() throws.

This returns alwaysFalse for startsWith and alwaysTrue for notStartsWith when the value is null, the same as in/notIn (#17014) and the row-level Evaluator. One consequence: deleteFromRowFilter(notStartsWith("s", "a")) now deletes null-partition files instead of failing, which is what notEqual and notIn already do.

New tests:

  • TestResiduals: null partition for startsWith and notStartsWith, and the or(isNull, startsWith) shape.
  • TestTruncatesResiduals: null partition under truncate.
  • TestDeleteFiles.testDeleteByStartsWithKeepsNullPartition: the delete above keeps the null-partition file.

AI Disclosure

  • Model: Claude Opus
  • Human Oversight: reviewed

ResidualVisitor.startsWith and notStartsWith dereferenced the partition
value without a null check, so computing a residual for a null partition
threw NullPointerException. This breaks deleteFromRowFilter(startsWith)
when a manifest also holds a null partition, and scan tasks for filters
such as or(isNull(s), startsWith(s, "a")). Mirror the in/notIn null
handling.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

API: ResidualEvaluator throws NullPointerException for null partition values in startsWith/notStartsWith

1 participant