david-mollitor-db opened a new pull request, #58484:
URL: https://github.com/apache/spark/pull/58484

   ### What changes were proposed in this pull request?
   
   `LikeSimplification` rewrites simple `LIKE` patterns into cheaper predicates 
(`'A%'` ->
   `StartsWith`, `'%B'` -> `EndsWith`, `'A%B'` -> length guard + `StartsWith` + 
`EndsWith`,
   `'%B%'` -> `Contains`, exact string -> `EqualTo`). Multi-wildcard patterns 
that have a
   *leading literal* but match none of those shapes -- e.g. `'A%B%'`, 
`'AB%CD%EF'`, `'A_B%'` --
   fall through unchanged and remain a full regex `Like`, so the data source 
receives no
   predicate and the per-row regex runs on every row.
   
   This PR makes `LikeSimplification` additionally derive the leading literal 
`A` as the
   necessary condition `StartsWith(col, A)`, keeping the original `LIKE` as the 
exact residual:
   
   ```
   col LIKE 'A%B%'  ==>  StartsWith(col, A) && (col LIKE 'A%B%')
   ```
   
   `StartsWith` is placed first so the cheap check short-circuits the regex. 
The derivation is
   restricted to binary-equality collations 
(`StringType.supportsBinaryEquality`, i.e.
   `UTF8_BINARY`) and a `TreeNodeTag` on the residual `Like` keeps the rule 
idempotent under the
   fixed-point optimizer batch. Only `StartsWith` is derived from the leading 
literal; the
   `LikeAll`/`LikeAny` paths are unchanged.
   
   ### Why are the changes needed?
   
   - **Pushdown / pruning.** On `UTF8_BINARY`, `StartsWith` translates to
     `sources.StringStartsWith`, which prunes Parquet row groups via min/max 
statistics. Readers
     cannot prune on the raw `Like`, so today a leading-literal multi-wildcard 
`LIKE` reads every
     row group.
   - **Cheaper per-row evaluation.** The `StartsWith` short-circuits the more 
expensive regex on
     rows that fail the prefix.
   - **Results are unchanged.** `StartsWith(A)` is implied by `LIKE 'A%...'`, 
and the exact `LIKE`
     is retained as the residual, so the conjunction accepts exactly the same 
rows. This mirrors
     how PostgreSQL, SQL Server and SQLite turn a leading-literal `LIKE` into a 
sargable prefix
     predicate plus a residual recheck.
   
   The derivation is gated on binary equality for correctness as well as 
benefit: under a
   collation-aware collation (e.g. `UTF8_LCASE`) the `Like` regex match (Java 
regex case flags)
   and `StartsWith` (`CollationSupport`) can disagree, so `StartsWith(A)` would 
not be a sound
   necessary condition; and `StringStartsWith` is pushed down only for 
`UTF8_BINARY` (non-binary
   is wrapped as `CollatedStringStartsWith`, which readers ignore). 
`EndsWith`/`Contains` are not
   derived from trailing/inner literals because Parquet's 
`StringEndsWith`/`StringContains` have
   `canDrop = false` (no pruning).
   
   ### Does this PR introduce _any_ user-facing change?
   
   No. Query results are identical; this is a performance improvement (added 
pushdown and a
   short-circuit conjunct on an otherwise unsimplified `LIKE`).
   
   ### How was this patch tested?
   
   - New unit tests in `LikeSimplificationSuite` covering: derivation for 
`'a%b%'`, a multi-char
     prefix with multiple wildcards, `'_'` patterns, no derivation when there 
is no leading literal,
     no derivation when the pattern contains the escape char, no derivation for 
a non-binary
     (`UTF8_LCASE`) collation, and idempotency.
   - A new end-to-end test in `ParquetFilterSuite` verifying that `LIKE 
'ab%cd%'` / `'ab%cd%ef'` /
     `'a_b%'` push a `StringStartsWith` and prune Parquet row groups.
   - `build/sbt 'catalyst/testOnly *LikeSimplificationSuite'` and
     `build/sbt 'sql/testOnly *ParquetV1FilterSuite -- -z "leading-literal"'` 
pass; scalastyle clean.
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Opus 4.8
   


-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to