jonasdedden opened a new pull request, #50989:
URL: https://github.com/apache/arrow/pull/50989

   ### Rationale for this change
   
   `starts_with`, `ends_with` and `match_substring` have no Substrait mapping, 
so any expression using them fails to serialize:
   
   ```python
   import pyarrow as pa
   import pyarrow.compute as pc
   from pyarrow.substrait import serialize_expressions
   
   schema = pa.schema([pa.field("cat", pa.string())])
   serialize_expressions([pc.starts_with(pc.field("cat"), "al")], ["f"], schema)
   # ArrowNotImplementedError: No conversion function exists to convert the
   # Arrow function starts_with to a Substrait call
   ```
   
   Comparisons, `isin` and arithmetic serialize fine, so this is a per-function 
gap. It matters for engines that ingest a PyArrow filter through Substrait, 
where an unmappable function becomes a hard failure rather than a fallback.
   
   See #50988.
   
   ### What changes are included in this PR?
   
   Map the three kernels onto `starts_with`, `ends_with` and `contains` from 
Substrait's `functions_string.yaml`, in both directions.
   
   The signatures do not line up. Substrait passes the pattern as a second 
argument, while the Arrow kernels are unary and carry it in 
`MatchSubstringOptions`. So:
   
   * encoding lifts `MatchSubstringOptions::pattern` out into a literal argument
   * decoding requires that argument to be a non-null string literal, and 
returns `NotImplemented` otherwise
   
   Substrait's `case_sensitivity` option maps onto `ignore_case`. 
`CASE_INSENSITIVE_ASCII` has no Arrow equivalent and returns `NotImplemented`.
   
   Both caveats are documented in `docs/source/cpp/acero/substrait.rst`.
   
   ### Are these changes tested?
   
   Yes.
   
   `Substrait.StringMatchExpressionSerialization` round-trips all three 
functions with and without `ignore_case`, plus a nested 
`invert(starts_with(...))`. `Substrait.StringMatchExpressionDeserialization` 
drives hand-written Substrait JSON to cover the default (no option) case and 
the two rejection paths.
   
   Both pass locally. The rest of `arrow-substrait-substrait-test` is 
unaffected (the only failures in my run were read-relation tests that need the 
`parquet-testing` submodule, which I had not checked out).
   
   `test_serializing_string_match_expressions` covers the PyArrow path. I was 
not able to build pyarrow locally, so that one has not run outside CI. Its 
assertion compares `str()` of the deserialized expression against a normalized 
form, following `test_serializing_multiple_expressions`; I checked that 
comparison holds for all seven parametrized cases by replicating it in C++ 
against the built libraries.
   
   ### Are there any user-facing changes?
   
   Yes. `pc.starts_with`, `pc.ends_with` and `pc.match_substring` can now be 
serialized to Substrait and consumed back, and Acero can consume plans using 
Substrait's `starts_with`, `ends_with` and `contains`. No existing behaviour 
changes: these previously raised.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to