Skip to content

feat(reader): extract per-zone SUM fold into reader.compute.ZoneReducer#183

Merged
dfa1 merged 2 commits into
mainfrom
feat/zone-reduce
Jun 27, 2026
Merged

feat(reader): extract per-zone SUM fold into reader.compute.ZoneReducer#183
dfa1 merged 2 commits into
mainfrom
feat/zone-reduce

Conversation

@dfa1

@dfa1 dfa1 commented Jun 27, 2026

Copy link
Copy Markdown
Owner

What

Moves the zone-map SUM fold out of the Calcite adapter into a reusable reader-side primitive — reader.compute.ZoneReducer.sum(column) — the whole-zone tier of ADR 0013 §6 aggregate push-down.

ZoneReducer.sum folds the per-zone SUM rows from ScanIterator.columnZoneStats with no data segment decoded, returning null when no zone carries a usable sum (no zone map, or an overflowed zone) so the caller streams instead. Semantics are identical to the inlined fold it replaces; VortexAggregates now delegates to it.

Why here

reader.compute is the seam a future vortex-compute module extracts. ZoneReducer depends only on the public reader scan API, so the extraction is mechanical once a second consumer (arrow bridge, query façade) lands. The reduce primitive belongs in reader, not the Calcite adapter.

Scope

ADR 0013 stays Proposed. The predicate/residual tier (boundary zones a WHERE partially selects) is deliberately not built here: it has no consumer yet — Calcite aggregates the whole column. The next increment wires Calcite aggregate + WHERE push-down (the consumer), then adds ZoneReducer predicate support on top.

Tests

  • ZoneReducerTest (writer module, round-trip): integer sum → exact Long; float sum → Double; no zone map → null.
  • VortexAdapterCoverageTest unchanged and green — Calcite behaviour is identical through the delegation.

🤖 Generated with Claude Code

dfa1 and others added 2 commits June 27, 2026 17:12
Move the zone-map SUM fold out of the Calcite adapter into a reusable
reader-side primitive (ADR 0013 §6, whole-zone tier). ZoneReducer.sum
folds the per-zone SUM rows from ScanIterator.columnZoneStats with no
data segment decoded, returning null when no zone carries a usable sum so
the caller streams instead — identical semantics to the inlined fold it
replaces.

Lives in reader.compute as the seam a future vortex-compute module
extracts: it depends only on the public reader scan API, so the move is
mechanical once a second consumer appears. The predicate/residual tier
waits on its consumer (Calcite aggregate + WHERE push-down).

VortexAggregates now delegates SUM to ZoneReducer; behaviour unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add an overflowed-zone case to ZoneReducerTest: zone maps enabled but one
I64 chunk's SUM overflows (Math.addExact drops it), so the zone-map table
is present yet a zone carries no usable sum — exercising the fold's bail
path distinctly from the absent-table case.

Also add WriteOptions.withZoneMaps(boolean), mirroring withGlobalDict /
withZstd, so the no-zone-map test reads as
WriteOptions.defaults().withZoneMaps(false) instead of a brittle
positional constructor call.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dfa1 dfa1 merged commit cfeb551 into main Jun 27, 2026
6 checks passed
@dfa1 dfa1 deleted the feat/zone-reduce branch June 28, 2026 10:45
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.

1 participant