Skip to content

fix: write and read decimal partition values in manifests - #9

Merged
pkonrad1229 merged 2 commits into
mainfrom
fix/decimal-partition-values
Oct 5, 2026
Merged

pkonrad1229 merged 2 commits into
mainfrom
fix/decimal-partition-values

Conversation

@pkonrad1229

@pkonrad1229 pkonrad1229 commented Oct 2, 2026 •

Copy link
Copy Markdown

Manifests with a decimal partition value could not be written, and if written, were corrupt and unreadable. Three independent bugs on the write → encode → read path:

  1. Write fails with EINVAL (manifest/manifest_adapter.cc). The partition struct's decimal child is a nanoarrow DECIMAL128 array, but the value was appended with ArrowArrayAppendBytes, which that array rejects. Now built as an ArrowDecimal and appended with ArrowArrayAppendDecimal.
  2. Corrupt Avro for precision < 38 (avro/avro_direct_encoder.cc, avro/avro_data_util.cc). Both encoders copied all 16 bytes of the Arrow decimal128 into an Avro fixed sized for the precision (e.g. 5 bytes for decimal(10,2)). Avro fixed carries no length, so the reader takes N bytes and every following field is decoded from the wrong offset. Now emit only the fixed's width (low-order bytes of the little-endian value), reversed to big-endian.
  3. Read fails with Unsupported type (manifest/manifest_reader.cc). ParsePartitionValues had no DECIMAL128 case. Added; it parses into Literal::Decimal with the field's precision and scale.

Tests

  • manifest_writer_versions_test: TestV2WriteDecimalPartitionValues writes and reads back a manifest partitioned on decimal(10,2) and decimal(38,10) (incl. the 38-digit minimum).
  • avro_test: WriteDecimalTypes round-trips precisions 1, 2, 3, 9, 10, 18, 19, 28, 38 — every boundary where the fixed width changes — with max, min, zero and one-ulp values, on both the direct-encoder and GenericDatum paths, and asserts the physical fixed size per precision. Fails on both paths with fix 2 reverted.
  • avro_data_test: existing decimal case now also asserts the encoded fixed is 5 bytes.

@pkonrad1229
pkonrad1229 marked this pull request as ready for review October 2, 2026 14:32
@pkonrad1229
pkonrad1229 force-pushed the fix/decimal-partition-values branch from d016d02 to 2bca716 Compare October 2, 2026 14:43
@pkonrad1229

Copy link
Copy Markdown
Author

Force-pushed: switched the new test's case table to designated initializers per clang-tidy.

@pkonrad1229
pkonrad1229 force-pushed the fix/decimal-partition-values branch from 2bca716 to cb5484b Compare October 2, 2026 15:33
The partition struct child for a decimal field is a nanoarrow DECIMAL128
array, which ArrowArrayAppendBytes rejects with EINVAL, so any manifest
entry carrying a decimal partition value failed to write. Append it as an
ArrowDecimal instead.

Both avro encoders copied all 16 bytes of a decimal128 into a fixed sized
for the precision (5 bytes for decimal(10,2)), corrupting the record for
any precision below 38. Emit only the fixed's width, big-endian.

The manifest reader had no case for decimal partition values, so a
manifest carrying one could not be read back. Parse them into decimal
literals.
Cover precisions 1 through 38 at every point where the Avro fixed
width changes, with max, min, zero and one-ulp values, on both the
direct encoder and GenericDatum write paths. Also assert the physical
fixed size per precision.
@pkonrad1229
pkonrad1229 force-pushed the fix/decimal-partition-values branch from cb5484b to 1152e1f Compare October 5, 2026 06:37
@pkonrad1229

Copy link
Copy Markdown
Author

force-push: rebased to get the CI fix from master. No code changes in this PRs commits

@pkonrad1229
pkonrad1229 merged commit 481336a into main Oct 5, 2026
38 checks passed
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.

2 participants