[SPARK-58096][SQL] Fix approx_top_k wrong counts/items for UNICODE-collated non-ASCII strings#57272
[SPARK-58096][SQL] Fix approx_top_k wrong counts/items for UNICODE-collated non-ASCII strings#57272jiwen624 wants to merge 2 commits into
Conversation
…lues via lossy sort-key decode
| this.original = original; | ||
| } | ||
|
|
||
| public String key() { |
There was a problem hiding this comment.
Dropped the unused key() accessor: nothing reads it, and exposing the raw sort-key byte[] leads to a risk of it being mutated externally.
|
Hi @cloud-fan this patch fixes the |
cloud-fan
left a comment
There was a problem hiding this comment.
0 blocking, 1 non-blocking, 0 nits.
Clean, well-scoped fix — keying on raw sort-key bytes matches the Mode analogue and correctly avoids the lossy-toString over-merge at both key-producing sites. One optional test-coverage note.
Suggestions (1)
- ApproxTopKSuite.scala:314: non-ASCII regression coverage is missing for the
accumulate/estimate/combine(serde deserialize) path — see inline
| } | ||
|
|
||
| // scalastyle:off nonascii | ||
| test("SPARK-58096: approx_top_k keys on raw sort-key bytes, not a lossy-decoded String, " + |
There was a problem hiding this comment.
The same lossy-toString bug also lived in ArrayOfCollatedStringsSerDe.wrap (the deserialize path), and the fix corrects it there too — but this new test only exercises the direct approx_top_k update path. The existing SPARK-58069 accumulate/combine tests above use ASCII-only fixtures ('HELLO'/'world'), which can't observe the over-merge, so the serde path currently has no non-ASCII regression guard. Consider mirroring this case through approx_top_k_estimate(approx_top_k_accumulate(...)) (and/or combine) to cover that second key-producing site. Non-blocking.
There was a problem hiding this comment.
Thanks. Added test coverage 👍
…ated approx_top_k over-merge
What changes were proposed in this pull request?
Follow-up to #57177.
approx_top_kon a non-binary collated string keyed its DataSketches item on getCollationKey(...).toString(). ICU sort keys are arbitrary bytes, not valid UTF-8, so .toString() lossily maps them to U+FFFD and merges collation-distinct values into one item with an inflated count. This changes CollatedString to key on the raw sort-key byte[] (via CollationFactory.getCollationKeyBytes), so key and original round-trip losslessly with no Java String intermediary. The on-wire serde format is unchanged (only original is persisted).Why are the changes needed?
Wrong counts for any UNICODE/UNICODE_CI/locale collation over non-ASCII data (e.g. 且/丕/世 collapse to one item). UTF8_BINARY and UTF8_LCASE are unaffected.
Does this PR introduce any user-facing change?
Yes — fixes incorrect approx_top_k counts/items for ICU-collated non-ASCII strings.
How was this patch tested?
Added UT case.
Was this patch authored or co-authored using generative AI tooling?
Yes