[UUID 2/8] UUID ingest and segment storage#18870
Conversation
1600368 to
6db6748
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #18870 +/- ##
============================================
+ Coverage 65.37% 65.40% +0.03%
Complexity 1405 1405
============================================
Files 3423 3423
Lines 215972 216102 +130
Branches 34186 34213 +27
============================================
+ Hits 141199 141350 +151
+ Misses 63399 63373 -26
- Partials 11374 11379 +5
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
ef90d01 to
6569e4a
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds UUID ingest- and segment-storage–level support, treating logical UUID as fixed-width 16-byte BYTES while layering UUID-specific behavior into segment-local components (forward index, dictionaries, min/max, bloom filters, Avro interop, and upsert PK normalization).
Changes:
- Add UUID-aware handling in segment storage paths (MV raw forward index, mutable dictionaries, stats/min-max, null virtual column).
- Add UUID normalization/validation in ingest (including upsert/dedup PK canonical-string enforcement) and UUID-aware hashing behavior for upsert PKs.
- Add Avro schema interop for
logicalType: "uuid"and segment-processing Avro export conversions (bytes ↔ canonical UUID string).
Reviewed changes
Copilot reviewed 36 out of 36 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| pinot-segment-spi/src/main/java/org/apache/pinot/segment/spi/index/creator/BloomFilterCreator.java | Store UUID bloom entries using canonical UUID strings (rather than hex/raw forms). |
| pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/HashUtilsTest.java | Add coverage for UUID hashing normalization and legacy-lenient UUID string handling. |
| pinot-segment-local/src/test/java/org/apache/pinot/segment/local/upsert/ConcurrentMapPartitionUpsertMetadataManagerTest.java | Update mocks to provide DataSourceMetadata.getFieldSpec() required by updated code paths. |
| pinot-segment-local/src/test/java/org/apache/pinot/segment/local/upsert/ConcurrentMapPartitionUpsertMetadataManagerForConsistentDeletesTest.java | Same as above for consistent-deletes upsert tests. |
| pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/readers/LazyRowTest.java | Update mocks to provide DataSourceMetadata/FieldSpec for column readers. |
| pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/loader/columnminmaxvalue/ColumnMinMaxValueGeneratorTest.java | Add regression test ensuring raw BYTES/UUID min/max metadata direction is correct. |
| pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/creator/BloomFilterCreatorTest.java | Add UUID bloom filter test where inputs are UUID bytes and lookups are UUID strings. |
| pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/column/DefaultNullValueVirtualColumnProviderTest.java | Extend null-virtual-column coverage to UUID (stored as BYTES). |
| pinot-segment-local/src/test/java/org/apache/pinot/segment/local/recordtransformer/DataTypeTransformerTest.java | Add tests for upsert/dedup UUID PK canonical string validation. |
| pinot-segment-local/src/test/java/org/apache/pinot/segment/local/realtime/impl/dictionary/MultiValueDictionaryTest.java | Add MV BYTES dictionary test and MV raw UUID-bytes forward-index test. |
| pinot-segment-local/src/test/java/org/apache/pinot/segment/local/indexsegment/mutable/MutableSegmentImplUuidPrimaryKeyTest.java | Add regression test for UUID PK normalization in MutableSegmentImpl PK construction. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/HashUtils.java | Make UUID hashing backward-compatible (lenient string parsing) while supporting non-string UUID inputs. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/readers/PinotSegmentColumnReader.java | Document BYTES comparator semantics also applying to canonical UUID bytes. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/readers/BytesDictionary.java | Minor cleanup in bytes dictionary implementation. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/loader/columnminmaxvalue/ColumnMinMaxValueGenerator.java | Fix raw BYTES/UUID min/max comparison direction (min/max inversion regression). |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/forward/ForwardIndexType.java | Enable fixed-width MV raw forward index for UUID (logical fixed width despite stored type BYTES). |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/column/DefaultNullValueVirtualColumnProvider.java | Treat UUID like BYTES for default-null dictionary creation. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/creator/impl/stats/NoDictColumnStatisticsCollector.java | Ensure partition stats for UUID use DataType.toString() (canonical UUID form). |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/creator/impl/stats/BytesColumnPreIndexStatsCollector.java | Same partition-stats fix for bytes/uuid pre-index stats collector. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/recordtransformer/DataTypeTransformer.java | Track UUID PK columns for upsert/dedup tables and enforce canonical lowercase UUID strings at ingest. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/realtime/impl/forward/FixedByteMVMutableForwardIndex.java | Add MV bytes read/write support (guarded for UUID fixed-width bytes). |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/realtime/impl/dictionary/BytesOnHeapMutableDictionary.java | Implement MV bytes indexing for on-heap bytes dictionary. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/realtime/impl/dictionary/BytesOffHeapMutableDictionary.java | Implement MV bytes indexing for off-heap bytes dictionary. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/realtime/converter/stats/MutableNoDictColumnStatistics.java | Document comparator correctness for UUID bytes under BYTES stored type. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/indexsegment/mutable/MutableSegmentImpl.java | Normalize UUID PK values into ByteArray (and UUID-specific ordering for raw forward index sorting). |
| pinot-segment-local/pom.xml | Add pinot-avro-base as a test dependency for new Avro UUID tests. |
| pinot-plugins/pinot-input-format/pinot-avro-base/src/test/java/org/apache/pinot/plugin/inputformat/avro/AvroUtilsTest.java | Add schema mapping tests for Avro UUID logical type (SV + MV). |
| pinot-plugins/pinot-input-format/pinot-avro-base/src/test/java/org/apache/pinot/plugin/inputformat/avro/AvroSchemaUtilTest.java | Add focused tests for schema-shape mapping helpers for UUID logical types. |
| pinot-plugins/pinot-input-format/pinot-avro-base/src/main/java/org/apache/pinot/plugin/inputformat/avro/AvroUtils.java | Emit Avro logicalType:uuid for UUID fields and recognize it during schema extraction. |
| pinot-plugins/pinot-input-format/pinot-avro-base/src/main/java/org/apache/pinot/plugin/inputformat/avro/AvroSchemaUtil.java | Add logical-type–aware valueOf(Schema) and emit UUID logical type in Avro JSON schema objects. |
| pinot-plugins/pinot-input-format/pinot-avro-base/src/main/java/org/apache/pinot/plugin/inputformat/avro/AvroIngestionSchemaValidator.java | Fix mismatch message to report inferred Pinot type (incl. UUID logical type) rather than raw Avro type. |
| pinot-core/src/test/java/org/apache/pinot/core/util/SegmentProcessorAvroUtilsTest.java | Add regression tests for UUID handling when exporting GenericRow to Avro records. |
| pinot-core/src/test/java/org/apache/pinot/core/segment/processing/genericrow/GenericRowSerDeTest.java | Extend GenericRow ser/de tests to include MV BYTES payloads (storage shape for MV UUID). |
| pinot-core/src/main/java/org/apache/pinot/core/util/SegmentProcessorAvroUtils.java | Convert UUID bytes to canonical UUID strings when writing Avro with uuid logical types; emit UUID schema. |
| pinot-core/src/main/java/org/apache/pinot/core/segment/processing/genericrow/GenericRowSerializer.java | Add MV BYTES serialization support (needed for MV UUID round-trip in segment processing). |
| pinot-core/src/main/java/org/apache/pinot/core/segment/processing/genericrow/GenericRowDeserializer.java | Add MV BYTES deserialization + comparison support (mirrors serializer). |
28af827 to
6132b99
Compare
f8c2c0c to
1f40de6
Compare
Jackie-Jiang
left a comment
There was a problem hiding this comment.
Please take a look at this comment: https://github.com/apache/pinot/pull/18870/changes#r3581672306
8a355af to
917440f
Compare
d26dcdb to
5c8525e
Compare
Jackie-Jiang
left a comment
There was a problem hiding this comment.
Mostly good. General goal is to reduce the special handling of UUID, because that usually indicates some bug in the contract
bfb965f to
16294c3
Compare
Part 2/8 of splitting apache#18140 (logical UUID type). Rebased onto master (now includes the merged apache#18869 type foundation); stacked on 92a0d98. Downstream references use the UuidKey class merged in apache#18869.
What
Ingest + segment-storage handling for UUID columns.
Changes
DataTypeTransformernormalizes UUID inputs (canonical string /java.util.UUID/byte[16]) to 16 bytesHashUtilsGenericRowser/de,SegmentProcessorAvroUtils; AvrologicalType: "uuid"interopBloomFilterCreator(segment-spi)Enables
Offline + realtime ingest, dictionary/raw encoding, bloom filters, and UUID-backed upsert primary keys.
Depends on
#18869 (
DataType.UUID,UuidUtils).About this PR / how to review
This is part 2 of 8 splitting #18140 (first-class logical
UUIDtype) into layered PRs, as requested there.The split is enabled by the v1 design:
DataType.UUIDhas stored typeBYTES, so most paths handle it automatically; each PR adds explicit UUID semantics to one subsystem. Head branch lives onxiangfu0/pinot.This PR is stacked on #18869 (branch
uuid-split/01-spi-foundation). Because GitHub PRs to apache must base onmaster, the Files-changed tab is cumulative (it includes layers 1–2) until the PRs below it merge. Review the commit titled[UUID 2/8] UUID ingest and segment storage— that is this layer's change. Each parent merge shrinks this diff after a rebase.Full stack (merge bottom → top)
After #18869 lands, PRs 2/4/7 (#18870, #18872, #18875) only depend on it and can be reviewed in parallel; PRs 5/6 (#18873, #18874) also need #18871; PR 8 (#18876) needs #18874.
Full feature description, v1 design contract, scope exclusions, and benchmark numbers: #18140.