Rework UUID type conversion to use java.util.UUID as the external form - #18927
Conversation
There was a problem hiding this comment.
Pull request overview
This PR standardizes Pinot’s UUID handling by making java.util.UUID the external representation in pinot-spi (PinotDataType), while keeping UUID stored internally as fixed 16-byte byte[] (and ByteArray where Pinot uses internal wrappers). It also extends UUID parsing to accept dashless 32-char hex strings so UUID default-null values can round-trip through string forms.
Changes:
- Reworks
PinotDataTypeUUID/UUID_ARRAY conversion APIs soconvert(...)returnsUUID/UUID[], whiletoInternal(...)returnsbyte[]/byte[][]. - Updates
FieldSpec.DataTypeUUID semantics to operate directly onbyte[]and documents each type’s expected in-memory representation. - Extends
UuidUtils.toBytes(String)to accept both RFC-4122 strings and 32-char dashless hex, with tests covering round-trips.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
pinot-spi/src/main/java/org/apache/pinot/spi/utils/UuidUtils.java |
Adds dashless-hex parsing fallback for UUID string → bytes. |
pinot-spi/src/test/java/org/apache/pinot/spi/utils/UuidUtilsTest.java |
Adds test for dashless hex UUID round-trip and updates invalid test cases. |
pinot-spi/src/main/java/org/apache/pinot/spi/utils/PinotDataType.java |
Changes UUID external form to UUID (and arrays), and moves JSON→UUID parsing into JSON.toUUID. |
pinot-spi/src/test/java/org/apache/pinot/spi/utils/PinotDataTypeTest.java |
Updates tests to reflect new UUID external form and validates toInternal behavior. |
pinot-spi/src/main/java/org/apache/pinot/spi/data/FieldSpec.java |
Aligns UUID values with byte[] stored type and updates equality/hash/compare/toString/convert behavior. |
d327210 to
4eefcdc
Compare
|
Reviewed this as the more complete replacement for #18926 (which I closed). Overall LGTM — establishing Verified ✔️
Nice catch worth a testThe Questions (non-blocking)
🤖 Automated review via Claude Code |
Establish a consistent internal/external representation for the UUID type: - PinotDataType: java.util.UUID is the external form and byte[] the internal form. UUID.convert / UUID_ARRAY.convert return UUID / UUID[], while toInternal returns byte[] / byte[][]. UUID.convert delegates to sourceType.toUUID, and every single-value type now defines toUUID so an unsupported conversion (e.g. INT -> UUID) throws a descriptive "Cannot convert value from INT to UUID" instead of a confusing "There is no single-value type" error. The JSON->UUID parsing moves into JSON.toUUID. Removes the now-unused toUuidBytesArray. - FieldSpec.DataType: UUID values are represented uniformly as byte[], matching the BYTES stored type. equals / hashCode / compare / toString drop the toBytesValue helper and operate on byte[] directly. Adds enum-level Javadoc documenting the in-memory value representation per type. - UuidUtils.toBytes(String) accepts the dashless 32-char hex form in addition to the canonical string, so byte[] default null values (stringified as raw hex) round-trip back through FieldSpec.getDefaultNullValue.
4eefcdc to
4ca914c
Compare
|
Thanks for the thorough review! Q1 (hex fallback scope): Keeping it global, intentionally. Q2 ( Test suggestion: Added |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #18927 +/- ##
=========================================
Coverage 64.81% 64.82%
Complexity 1347 1347
=========================================
Files 3396 3396
Lines 212503 212481 -22
Branches 33484 33475 -9
=========================================
+ Hits 137732 137734 +2
+ Misses 63610 63585 -25
- Partials 11161 11162 +1
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:
|
Summary
Establishes a consistent internal/external representation for the
UUIDtype acrosspinot-spi.PinotDataTypejava.util.UUIDis now the external form andbyte[]the internal form.UUID.convert/UUID_ARRAY.convertreturnUUID/UUID[], whiletoInternalreturnsbyte[]/byte[][].UUID.convertdelegates tosourceType.toUUID(...), and every single-value type now definestoUUID. Unsupported conversions (e.g.INT -> UUID) throw a descriptiveCannot convert value from INT to UUIDrather than the confusingThere is no single-value type ...that leaked from the generic fallback. This mirrors how each type already overridestoBytes/toTimestamp.JSON.toUUID. The now-unusedtoUuidBytesArrayis removed.FieldSpec.DataTypeUUIDvalues are represented uniformly asbyte[], matching theBYTESstored type.equals/hashCode/compare/toStringdrop thetoBytesValueindirection and operate onbyte[]directly.convertInternalreturns the internal storage form (ByteArrayforBYTES/UUID).UuidUtilstoBytes(String)accepts the dashless 32-char hex form in addition to the canonical string, sobyte[]default null values (stringified as raw hex) round-trip back throughFieldSpec.getDefaultNullValue.