Skip to content

fix: force partition fields nullable in partitionValues_parsed schema#2420

Closed
DrakeLin wants to merge 2 commits intodelta-io:mainfrom
DrakeLin:drake-lin_data/fix-partition-nullable-checkpoint
Closed

fix: force partition fields nullable in partitionValues_parsed schema#2420
DrakeLin wants to merge 2 commits intodelta-io:mainfrom
DrakeLin:drake-lin_data/fix-partition-nullable-checkpoint

Conversation

@DrakeLin
Copy link
Copy Markdown
Collaborator

@DrakeLin DrakeLin commented Apr 17, 2026

What changes are proposed in this pull request?

Forces all partition fields to be nullable in build_partition_values_parsed_schema. The checkpoint parquet format is sparse: each row is one action type, and all other action types' columns are null. Non-add rows have no partition values, so partitionValues_parsed fields must be nullable regardless of the table schema.

Without this fix, tables with non-nullable partition columns and writeStatsAsStruct=true fail checkpoint creation with Arrow(InvalidArgumentError("Found unmasked nulls for non-nullable StructArray field ..."))`.

The longer-term fix is to force the entire checkpoint output schema nullable (#2439).

How was this change tested?

New round trip integration test with non-nullable partition column

@DrakeLin DrakeLin requested a review from scottsand-db April 17, 2026 22:04
@DrakeLin DrakeLin requested a review from dengsh12 April 17, 2026 22:05
@DrakeLin DrakeLin marked this pull request as ready for review April 17, 2026 22:05
@DrakeLin DrakeLin changed the title fix: force partition fields nullable in checkpoint partitionValues_parsed schema fix: force partition fields nullable in partitionValues_parsed schema Apr 17, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 17, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.35%. Comparing base (8d3e10a) to head (11f7cb7).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2420      +/-   ##
==========================================
- Coverage   88.35%   88.35%   -0.01%     
==========================================
  Files         171      171              
  Lines       57025    57024       -1     
  Branches    57025    57024       -1     
==========================================
- Hits        50383    50382       -1     
  Misses       4714     4714              
  Partials     1928     1928              

☔ View full report in Codecov by Sentry.
📢 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.

Comment thread kernel/src/table_configuration.rs Outdated
Comment thread kernel/tests/checkpoint_transform.rs Outdated
Comment thread kernel/tests/checkpoint_transform.rs Outdated
Comment thread kernel/tests/checkpoint_transform.rs Outdated
Copy link
Copy Markdown
Collaborator

@scottsand-db scottsand-db left a comment

Choose a reason for hiding this comment

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

LGTM! Minor comments PTAL

Copy link
Copy Markdown
Collaborator

@dengsh12 dengsh12 left a comment

Choose a reason for hiding this comment

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

Looks good! Just several questions

Comment thread kernel/src/table_configuration.rs Outdated
Comment on lines +298 to +300
/// and field types are the actual partition column data types. All fields are forced nullable
/// because partition values are derived from map lookups (`MAP_TO_STRUCT` over the
/// string-valued `partitionValues` map), which can return null for any missing key.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Seems not accurate? IIRC map keys are not missing. All fields are forced nullable here because we use the schema to transform all rows in checkpoint, and the not-add rows will not have partition values

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Updated comment

Comment thread kernel/src/table_configuration.rs Outdated
field.physical_name(column_mapping_mode).to_owned(),
field.data_type().clone(),
field.is_nullable(),
true, // Always nullable: values come from map lookups
Copy link
Copy Markdown
Collaborator

@dengsh12 dengsh12 Apr 21, 2026

Choose a reason for hiding this comment

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

This seems not the ideal fix? E.g. if somehow data is corrupted, and there is an add action with a null partition value in a non-null partition field, we will not error. Feel like the idea fix is to extra partition_value_parsed for add action only, with the nullability retained from table schema? Perhaps a less concern -- I'm okay with this as a short term fix if the idea fix is not easy to implement

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed the schema can't enforce this on its own since it's shared across all row types. Filed #2439 to force the entire checkpoint output schema nullable as a potential followup

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm not pretty sure if we want all fields in checkpoint schema to be nullable -- seems loosing validations? e.g. if we make add.path nullable, there may be an add action without path(but not in this PR's scope, we can discuss later under #2439)

For current fix, I'm still wondering if we can retain the nullability from the table schema, and only run map_to_struct for add actions? Seems that will also fix the problem and defending data corruption. If that's complex I'm good with current fix

@DrakeLin DrakeLin force-pushed the drake-lin_data/fix-partition-nullable-checkpoint branch from 0fe95dd to 11f7cb7 Compare April 21, 2026 21:31
@DrakeLin DrakeLin requested a review from dengsh12 April 21, 2026 22:08
@DrakeLin
Copy link
Copy Markdown
Collaborator Author

closing in favor of github issue as long-term fix.
#2419 address immediate issue

@DrakeLin DrakeLin closed this Apr 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants