xiangfu0 opened a new pull request, #19308:
URL: https://github.com/apache/pinot/pull/19308
Stacked on #19307 (`xiangfu0/codex/codec-stack/05-v7-format`). Part of the
split of #18229.
## Summary
This is the enabling PR of the series: it removes every remaining
`codecSpec` feature-gate site and
replaces the gates with real behavior — semantic table-config-time
validation, reload/rewrite support in
`ForwardIndexHandler`, and rollback back to the legacy formats.
### Reload / rewrite (`ForwardIndexHandler`)
`shouldChangeRawCompressionType` is replaced by
`shouldRewriteRawForwardIndex`, which handles every
combination of existing on-disk format × new config:
| Existing on disk | New config | Decision |
|---|---|---|
| Legacy raw (compression C1) | no codecSpec, compression C2 | rewrite iff
C1 != C2 (unchanged legacy behavior) |
| Legacy raw (compression C1) | codecSpec mapping to legacy C2 | rewrite iff
C1 != C2 (stays in legacy format) |
| Legacy raw | codecSpec needing V7 (transform/chain/non-default options) |
rewrite to V7 codec-pipeline format |
| V7 (stored canonical spec S1) | codecSpec needing V7, canonical S2 |
rewrite iff S1 != S2 |
| V7 | codecSpec mapping to a legacy compression | rewrite back to the
legacy raw format |
| V7 | no codecSpec, explicit legacy `compressionCodec` (incl.
`PASS_THROUGH`) | rewrite back to the legacy format (**rollback path** —
`isLegacyRevertTargetForFixedByteSv`) |
| V7 | no codecSpec, no compressionCodec | no-op |
Change detection compares **canonical** specs on both sides: the stored side
is already canonical (V7
headers persist `CodecPipelineExecutor.getCanonicalSpec()`), and the
configured side is canonicalized by
running it through `CodecPipelineExecutor.create(...)` — never
`toDslString()` or the raw config string —
so semantically identical specs (e.g. differently-spelled defaults) never
trigger a rewrite, and an
unchanged config is always a no-op.
V7 detection is positive (`reader.getCodecSpec() != null`), not inferred
from a null compression type; a
legacy raw reader returning a null `ChunkCompressionType` now fails loudly
instead of silently skipping.
### Gate removal (all remaining sites)
- `ForwardIndexType.validate` — gate replaced by `validateCodecSpec(...)`,
run only for enabled forward
indexes: parses/validates the pipeline via the public
`CodecPipelineExecutor.create` entry point
(unknown codec, transform ordering, per-codec type compatibility) and
enforces the V7 writer's shape
constraints (single-value INT/LONG) for specs the legacy raw formats
cannot serve. Precise errors
replace the generic gate message.
- `ForwardIndexType.shouldCreateIndex` — gate removed; codecSpec configs
flow to the creator factory
(wired in the previous PR).
- `ForwardIndexType.createMutableIndex` — gate removed. Matching the
original #18229 behavior, the
mutable (consuming) forward index builds the standard in-memory format and
deliberately ignores
codecSpec: the spec applies when the consuming segment is
converted/committed to an immutable
segment. Realtime tables with a codecSpec consume normally.
- `ForwardIndexHandler.computeOperations` — the fail-fast guard from the
previous PR is replaced by the
real decision logic above.
- `OpenStructIndexType` / `OpenStructColumnSplitter` — **kept as a
deliberate rejection**, reworded from
the temporary gate message to `"codecSpec is not supported for OPEN_STRUCT
key: %s"`. The original
#18229 never wired codecSpec into OPEN_STRUCT per-key child columns (the
splitter builds its own child
forward configs with a fixed LZ4 raw compression and would silently
discard a per-key codecSpec), so an
explicit rejection is the honest behavior rather than silent config loss.
### Docs
- `FieldConfig.CompressionCodec` constants get "prefer codecSpec" guidance
in the new comma-list syntax
(`SNAPPY`→`"SNAPPY"`, `ZSTANDARD`→`"ZSTD(3)"`, `DELTA`→`"DELTA,LZ4"` with
the on-disk-semantics
caveat, etc.); `getCompressionCodec()` documents that it remains the only
way to express
`MV_ENTRY_DICT` and the CLP family.
- `TableConfigUtils` comment updated to the final behavior (codecSpec is
validated on the resolved
`ForwardIndexConfig` via `IndexType.validate`, so
`noDictionaryColumns`-resolved RAW columns work).
## Tests
- `ForwardIndexHandlerTest`: V7 no-op on unchanged canonical spec; V7
spec-change rewrite; V7
compression-only spec rewritten back to legacy raw; V7→legacy
`compressionCodec` rollback with full
value verification; legacy→equivalent codecSpec no-op; legacy→different
compression-only codecSpec
rewrite; legacy `DELTA`/`DELTADELTA` → V7 `DELTA,LZ4`/`DELTADELTA,LZ4`
migration reload preserving all
values across chunks.
- `TableConfigUtilsTest`: gate-rejection test replaced by
`testCodecSpecValidation` — accepts valid specs
(compression-only on any RAW column incl. STRING/MV, transform chains on
SV INT/LONG,
`noDictionaryColumns`-resolved RAW), rejects invalid ones with precise
errors (unknown codec, transform
after packing transform, V7-requiring specs on MV or non-INT/LONG columns).
- `ForwardIndexTypeTest`: mutable-index gate test replaced — a codecSpec
config now builds the standard
mutable forward index for realtime consumption.
- `ForwardIndexCreatorFactoryTest`: `shouldCreateIndex` gate test flipped to
acceptance.
- `OpenStructIndexTypeTest` / `OpenStructColumnSplitterTest`: assertions
updated to the permanent
rejection message.
## Deliberately excluded
- `CompressionCodecMigrator` and its tests (present in the original #18229)
are dropped from the series
entirely — legacy `DELTA`/`DELTADELTA` columns migrate through the normal
reload path instead, covered
by `testLegacyTransformMigrationReloadPreservesValues`.
- codecSpec on OPEN_STRUCT per-key child columns is explicitly rejected (see
above); no later PR in this
series adds it.
The final slice (integration tests + design doc) follows this PR but adds no
production code.
## Why master stays safe with only this merged
This PR is the gate-opener, so unlike the earlier slices it *does* activate
the feature — safety comes
from the pipeline being complete underneath it:
- All runtime pieces (DSL, validator, executor, transforms, V7 format,
creator/reader wiring) merged in
the previous five PRs; this PR only removes the gates and adds the reload
logic.
- No existing config changes behavior: columns without `codecSpec` follow
the exact pre-series code
paths (the legacy compression-change comparison is byte-for-byte the old
logic), and reload of a
segment with an unchanged config is a no-op.
- Rollback is first-class: reverting a table config from `codecSpec` to a
legacy `compressionCodec`
(or an equivalent compression-only spec) rewrites segments back to the
legacy formats readable by
pre-V7 servers.
- Realtime ingestion is unaffected: the mutable index ignores codecSpec; it
only applies at segment
conversion.
- Mixed-version caution still applies as designed for the series: V7
segments are only produced when an
operator explicitly configures a V7-requiring codecSpec, and older servers
cannot read them — the
standard guidance (finish the server rollout before adopting V7-requiring
specs) is unchanged from
#18229.
## Verification
```
./mvnw -q -T 1C install -DskipTests -Ppinot-fastdev -pl
pinot-spi,pinot-segment-spi,pinot-segment-local -am
./mvnw -q test -Ppinot-fastdev -pl pinot-segment-local \
-Dtest=ForwardIndexHandlerTest,TableConfigUtilsTest,ForwardIndexTypeTest,CodecPipelineForwardIndexTest,OpenStructIndexTypeTest,OpenStructColumnSplitterTest,ForwardIndexCreatorFactoryTest
\
-Dsurefire.failIfNoSpecifiedTests=false
./mvnw spotless:apply license:format -pl pinot-spi,pinot-segment-local
./mvnw checkstyle:check license:check -pl pinot-spi,pinot-segment-local
```
Result: all tests pass. The stack root is synced with master, so this branch
includes the #19282
chunk-caching fix that `testLegacyTransformMigrationReloadPreservesValues`
depends on (verified: a
523-test batch across the codec suite at the chain tip runs green, including
both migration variants
and `ForwardIndexHandlerContextTest`).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]