GH-3735: Use unsigned UTF-8 byte order for Variant object field keys - #3746
Open
peterxcli wants to merge 1 commit into
Open
GH-3735: Use unsigned UTF-8 byte order for Variant object field keys#3746peterxcli wants to merge 1 commit into
peterxcli wants to merge 1 commit into
Conversation
… keys The Variant spec requires object field ids to be sorted by the unsigned byte order of the field names' UTF-8 encoding, so readers can binary search them. VariantBuilder sorted fields - and Variant.getFieldByKey binary-searched them - with String.compareTo, which orders UTF-16 code units instead. The two orders diverge for keys containing supplementary-plane characters (U+10000 and above). - Add VariantUtil.encodeKey/compareKeys and use them when sorting object fields and binary-searching by key (adapted from apache#3736) - Retry lookups in UTF-16 order for keys containing code units at or above U+D800, so objects written before this fix remain readable Co-authored-by: rayokota <rayokota@gmail.com>
peterxcli
force-pushed
the
claude/equivalence-fix-9340dd
branch
from
August 25, 2026 01:45
0fdc9ac to
28c2621
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rationale for this change
The Variant encoding specification requires the field ids in an object's header to be sorted by the unsigned byte order of the field names' UTF-8 encoding, so readers can binary-search them.
VariantBuildersorted the fields — andVariant.getFieldByKeybinary-searched them — usingString.compareTo, which orders UTF-16 code units instead.The two orderings agree for all keys in the Basic Multilingual Plane but diverge for supplementary-plane characters (U+10000 and above):
String.compareToorders a leading high surrogate (0xD800–0xDBFF) before code points in U+E000..U+FFFF, whereas UTF-8 byte order (and the spec) orders them after. Consequences:This adapts #3736 by @rayokota and adds the read-compatibility fallback from the equivalent Spark fix (apache/spark#58239), per the discussion on that PR.
What changes are included in this PR?
VariantUtil.encodeKey(String)andVariantUtil.compareKeys(byte[], byte[]), which order field names by unsigned lexicographic UTF-8 byte order (from GH-3735 Fix Variant field name comparisons to use UTF-8 byte order #3736)VariantBuilder.FieldEntry.compareTosorts object fields with that comparison, lazily caching each field's UTF-8 encoding (from GH-3735 Fix Variant field name comparisons to use UTF-8 byte order #3736)Variant.getFieldByKeybinary-searches in UTF-8 byte order first; for keys containing a code unit at or above U+D800 (the only keys where the two orders can differ), it retries the search in UTF-16 order, so objects written by older versions in the legacy order remain readableAre these changes tested?
Three new tests in
TestVariantObjectBuilder:testObjectKeysSortedByUtf8ByteOrder— builds an object with keys U+FFFF (EF BF BF) and U+10000 (F0 90 80 80) appended in reverse and asserts the encoded field order is U+FFFF then U+10000 (UTF-8 order), which the previouscompareToreversed.testLargeObjectBinarySearchWithSupplementaryKey— a 42-field object (aboveBINARY_SEARCH_THRESHOLD) mixing ASCII keys with U+FFFF and U+10000, assertinggetFieldByKeyresolves both through the binary-search path.testLegacyUtf16OrderedObjectLookup— rewrites a canonical object's id and offset lists into the legacy UTF-16 order and assertsgetFieldByKeystill finds ASCII, U+FFFF, and U+10000 keys through the fallback search, and that absent keys stay absent.All 183
parquet-varianttests and theparquet-avrovariant read/write suites pass locally.Are there any user-facing changes?
Newly written Variant objects containing supplementary-plane field keys now use the specification's unsigned UTF-8 field order. Objects written in the legacy UTF-16 order remain readable via
getFieldByKey.Closes #3735
🤖 Generated with Claude Code