[
https://issues.apache.org/jira/browse/FLINK-41180?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Ramin Gharib reassigned FLINK-41180:
------------------------------------
Release Note: VARIANT objects now store their fields in the unsigned UTF-8
byte order of the field names, as the Variant spec requires. For field names
with a code point from U+E000 up, the order can differ from earlier versions.
This shows in {{getFieldNames}} and in {{CAST}} to {{STRING}}. Earlier versions
can miss such fields in objects of 32 or more fields that this version writes.
Objects that earlier versions wrote are still read correctly. A VARIANT object
with such keys that was stored before the upgrade is not byte equal to the same
object built after it.
Assignee: Ramin Gharib
> VARIANT objects sort and search field names in UTF-16 order instead of UTF-8
> byte order
> ---------------------------------------------------------------------------------------
>
> Key: FLINK-41180
> URL: https://issues.apache.org/jira/browse/FLINK-41180
> Project: Flink
> Issue Type: Bug
> Components: API / Core
> Reporter: Ramin Gharib
> Assignee: Ramin Gharib
> Priority: Major
> Fix For: 2.4.0
>
>
> The Parquet Variant spec orders the fields of an object by their names,
> "sorted lexicographically (using unsigned byte ordering for UTF-8)". Flink
> sorts and searches them with {{String.compareTo}}, which is UTF-16 order:
> {code:java}
> // BinaryVariantInternalBuilder.FieldEntry
> public int compareTo(FieldEntry other) {
> return key.compareTo(other.key);
> }
> // BinaryVariant.getFieldByKey, binary search for objects with 32 or more
> fields
> int cmp = getMetadataKey(metadata, id).compareTo(key);
> {code}
> The two orders differ when, at the first differing character, one name has a
> character from U+10000 up and the other one from U+E000 to U+FFFF. U+FF61 is
> {{EF BD A1}} in UTF-8 and U+1F600 is {{F0 9F 98 80}}, so the spec puts U+FF61
> first. UTF-16 compares {{FF61}} with {{D83D}} and puts U+1F600 first.
> h3. Impact
> An object in spec order, for example one written by another engine, can hide
> a field from {{getField}}. Probe on master: ASCII keys {{k00}}, {{k01}}, ...
> plus U+FF61 = 100 and U+1F600 = 200, with the last two fields swapped into
> spec order:
> ||Fields||getField(U+FF61)||getField(U+1F600)||
> |31|100|200|
> |32|100|null|
> |40|100|null|
> Below 32 fields the lookup is a linear scan, so the order does not matter
> there.
> The other direction has the same cause. Flink writes objects that are not in
> spec order, so a reader that binary-searches in byte order can miss their
> fields. Spark switched to UTF-8 order in SPARK-58949 and retries in UTF-16
> order on a miss, so it still reads older values. parquet-java switched in
> apache/parquet-java#3746. Not tested against a specific reader.
> h3. Proposal
> * Sort object fields by their stored UTF-8 key bytes, unsigned, in the
> builder.
> * Binary-search in the same byte order.
> * Keep values that are already written in UTF-16 order readable, since they
> live in state, savepoints and external systems. On a miss, fall back to a
> linear scan, but only when the wanted key has a byte of 0xEE or above. For
> any other key both orders agree, so a miss is a real miss.
> Sorting by the stored bytes also fixes keys with an unpaired surrogate in
> objects with 32 or more fields. The builder stores {{"a\uD800"}} as the bytes
> of {{"a?"}} but sorts it as {{"a\uD800"}}, so today neither spelling finds
> the field.
> h3. Compatibility
> Objects written after the change can have a different field order. A Flink
> version without the change can miss such keys in them.
> Related: FLINK-41110 compares UTF-8 bytes in the linear search.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)