Repository navigation
feat: Add Spark-compatible encode function to datafusion-spark - #21331
Conversation
|
run benchmarks |
|
Hi @Zeel-e6x, thanks for the request (#21331 (comment)). Only whitelisted users can trigger benchmarks. Allowed users: Dandandan, Fokko, Jefffrey, Omega359, adriangb, alamb, asubiotto, brunal, buraksenn, cetra3, codephage2020, comphead, erenavsarogullari, etseidl, friendlymatthew, gabotechs, geoffreyclaude, grtlr, haohuaijin, jonathanc-n, kevinjqliu, klion26, kosiew, kumarUjjawal, kunalsinghdadhwal, liamzwbao, mbutrovich, mzabaluev, neilconway, rluvaton, sdf-jkl, timsaucer, xudong963, zhuqi-lucas. File an issue against this benchmark runner |
xanderbailey
left a comment
There was a problem hiding this comment.
Looks good to me but you’ll need a committer to Approve also! Thanks for the PR!
|
Hey @xanderbailey, Do I need to mention the maintainers for review? if yes please suggest whom incase you know. |
|
They will normally pick it up within a week or so. If not we can ping them here. |
|
Thanks @xanderbailey and @JeelRajodiya -- the PR load is pretty intense! I started the CI for this PR |
22a2705 to
bf46433
Compare
|
I pushed the fixes for clippy errors. @alamb Can you rerun the checks please? |
|
Please rerun the checks |
| } | ||
| Ok(bytes) | ||
| } | ||
| _ => exec_err!( |
There was a problem hiding this comment.
Spark also supports UTF-32. It would be worth adding a comment here explaining why this isn't or can't be supported.
arguments = """
Arguments:
* str - a string expression
* charset - one of the charsets 'US-ASCII', 'ISO-8859-1', 'UTF-8', 'UTF-16BE', 'UTF-16LE', 'UTF-16', 'UTF-32' to encode `str` into a BINARY. It is case insensitive.
""",
There was a problem hiding this comment.
I missed adding support for UTF-32, I've added it now with respective tests.
55f4694 to
835ae8d
Compare
Implements `encode(string_or_binary, charset)` that converts a string or binary value into binary using the specified character encoding, matching Apache Spark's behavior.
In ANSI mode (default), encoding a character that cannot be represented in the target charset (e.g. non-ASCII char in US-ASCII) returns an error. In legacy mode, unmappable characters are silently replaced with '?'.
835ae8d to
6cb99a7
Compare
|
Thanks for iterating on this @JeelRajodiya. One issue I noticed: This PR returns Once challenge for this PR is that there is different behavior across Spark versions for the |
…ry types and use the binary arm in encode_dispatch
| DataType::Utf8 | ||
| | DataType::LargeUtf8 | ||
| | DataType::Utf8View | ||
| | DataType::Binary |
There was a problem hiding this comment.
does Spark also operate on binary types for this function? source code here seems to suggest only strings
There was a problem hiding this comment.
Not directly, but Spark Catalyst’s Analyzer inserts the cast specifically through the ImplicitTypeCasts coercion rule.
Thus:
encode(binary_value, 'UTF-8')is analyzed as:
encode(CAST(binary_value AS STRING), 'UTF-8')We preserve binary input in coerce_types instead of letting DataFusion cast it to a string because:
- Spark’s binary-to-string cast preserves malformed bytes, and
encodelater converts them toU+FFFD. - DataFusion’s normal Arrow binary-to-UTF8 cast rejects malformed UTF-8 before
encoderuns.
Example: X'FF' is malformed UTF-8. Spark’s encode path converts it to U+FFFD, while DataFusion’s normal binary-to-UTF8 cast returns an invalid UTF-8 error.
There was a problem hiding this comment.
this is worth leaving a comment here about (keep it succinct and to the point)
|
Thank you for your contribution. Unfortunately, this pull request is stale because it has been open 60 days with no activity. Please remove the stale label or comment or this will be closed in 7 days. |
Co-authored-by: Jeffrey Vo <jeffrey.vo.australia@gmail.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #21331 +/- ##
========================================
Coverage 81.53% 81.53%
========================================
Files 1123 1124 +1
Lines 406042 406294 +252
Branches 406042 406294 +252
========================================
+ Hits 331059 331271 +212
- Misses 55621 55652 +31
- Partials 19362 19371 +9 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
I'm still working on the PR |
| DataType::Utf8 | ||
| | DataType::LargeUtf8 | ||
| | DataType::Utf8View | ||
| | DataType::Binary |
There was a problem hiding this comment.
this is worth leaving a comment here about (keep it succinct and to the point)
Co-authored-by: Jeffrey Vo <jeffrey.vo.australia@gmail.com>
…ecty Co-authored-by: Jeffrey Vo <jeffrey.vo.australia@gmail.com>
|
if it looks good, Can we get this merged @Jefffrey ? |
|
thanks @JeelRajodiya & co sorry it hung for so long |
Rationale
The
datafusion-sparkcrate is missing theencodefunction. Spark'sencode(expr, charset)converts a string or binary value into binary using a specified character encoding — commonly used in Spark SQL workloads and needed by engines built on DataFusion that target Spark compatibility.What changes are included in this PR?
Adds
SparkEncodetodatafusion-spark's string functions, emulating Spark 3.5 semantics. It supports US-ASCII, ISO-8859-1, UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, and UTF-32LE, including common aliases (UTF8,LATIN1, etc.) and case-insensitive matching. The charset can be a constant or a per-row column. Binary input is decoded as lossy UTF-8 (invalid bytes → U+FFFD) before re-encoding, and unmappable characters are silently replaced with?, matching Spark.Are these changes tested?
Yes. Coverage lives in
encode.slt(sqllogictest) and exercises all charsets and aliases, case-insensitive matching, null value/charset handling, per-row charsets, binary input (Binary/LargeBinary/BinaryView) with lossy UTF-8,Utf8Viewinput, and the unsupported-charset error. A Rust unit test covers return-field nullability.Are there any user-facing changes?
New
encodescalar function available when usingdatafusion-spark.