You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ScanIterator.buildChunks rejected any per-column chunk mismatch beyond the
narrow 1-vs-N case ("mixed per-column chunking beyond 1-vs-N is not supported"),
so two Raincloud files the Rust oracle reads fine failed to scan.
Replace the 1-vs-N special case with the Rust reference's policy: the scan
planner now splits at the merged boundary grid — the sorted, deduplicated union
of every column's chunk boundaries. This mirrors vortex-layout's
StructReader::register_splits, which unions each field child's chunk boundaries
into one RowSplits set (vortex-layout/src/scan/split_by.rs), the scan then
walking each adjacent-boundary window and slicing every column's covering chunk
to it. The merged grid refines every column's grid, so each window lies entirely
within exactly one chunk of each column.
Tier decision: the merged-grid generalization is tractable and subsumes both
tiers from the issue, so it is implemented in full rather than only the nested
tier:
- nested boundaries (emotions-dataset-for-nlp: label [131072 x3, 23593] nests
inside text's 16384 grid), and
- disjoint boundaries (uci-beijing-multi-site-air-quality: numeric
[131072 x3, 27552] vs station's 40960/49152 grid, which do not nest)
both fall out of the union with no tier-specific code.
Fast paths are preserved: when a window equals a whole covering chunk (offset 0,
window rows == flat rows) the chunk is decoded straight into the chunk's arena
with no slice wrapper, so aligned N-vs-N and per-chunk decode stay zero-copy. A
coarse chunk that spans several windows is decoded once into the iterator's
shared arena (cached by identity) and sliced zero-copy per window, never
re-decoded.
Corpus evidence (CLI export vs the Parquet oracle):
uci-beijing-multi-site-air-quality: OK (420768 rows x 18 cols)
emotions-dataset-for-nlp: OK (416809 rows x 2 cols)
Both matrix entries flipped gap:221 -> ok; conformance suite green.
Closes#221
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
10
10
### Fixed
11
11
12
+
- Scans of files whose columns use different chunk grids no longer fail with `mixed per-column chunking beyond 1-vs-N is not supported`. The scan planner now splits at the merged boundary grid — the sorted union of every column's chunk boundaries, matching the Rust reference — and decodes each column's covering chunk once, slicing it zero-copy to each window. This handles both nested grids (Raincloud `emotions-dataset-for-nlp`, where `label`'s coarse chunks nest inside `text`'s finer grid) and disjoint grids (`uci-beijing-multi-site-air-quality`, where numeric and `station` boundaries do not nest). Aligned N-vs-N and 1-vs-N scans keep their existing slice-free fast path. ([#221](https://github.com/dfa1/vortex-java/issues/221))
12
13
- CSV export renders nested struct columns as JSON object cells (`{"field":value,...}`, strings JSON-escaped, null fields as JSON `null`, nested structs recursed) instead of throwing `unsupported array type: StructArray`. ([#217](https://github.com/dfa1/vortex-java/issues/217))
13
14
- Scanning a struct whose columns include a nested struct no longer fails chunk planning. A nested `vortex.struct` layout column (e.g. Raincloud `countries-of-the-world`'s `data` column) is now treated as a single full-range chunk source and decoded through the layout registry's new struct decoder into a `StructArray`, matching the Rust reference (a nested struct spans its parent's row range, not an independent chunking). `schema`/`count`/`inspect` already worked; plain scans and `select` of sibling columns now work too. CSV export of the struct column itself remains unsupported (a separate rendering limitation). ([#207](https://github.com/dfa1/vortex-java/issues/207))
14
15
- CSV export renders unsigned integer columns (U8–U64) with their unsigned values — high-half values previously printed as two's-complement negatives (uci-wine `magnesium` U8 132 exported as -124), silent corruption found by the Raincloud conformance suite. ([#208](https://github.com/dfa1/vortex-java/issues/208))
@@ -863,7 +871,7 @@ public SegmentSpec segmentSpec(int index) {
863
871
// ── Internal record ───────────────────────────────────────────────────────
864
872
865
873
@SuppressWarnings("java:S6218") // internal data carrier; record components are arrays of immutable primitives or refs that flow through pipelines without ever being compared.
0 commit comments