kosiew commented on code in PR #26468:
URL: https://github.com/apache/datafusion/pull/26468#discussion_r4492201365


##########
datafusion/sqllogictest/test_files/strings.slt:
##########
@@ -361,6 +361,149 @@ p2
 p2e1
 p2m1e1
 
+# LIKE ANY
+query T rowsort
+SELECT s FROM test WHERE s LIKE ANY ('p1%', '%m1%');
+----
+P1m1e1
+p1
+p1e1
+p1m1e1
+p2m1e1
+
+query T rowsort
+SELECT s FROM test WHERE s LIKE ANY ('e1');
+----
+e1
+
+# NOT applies to each pattern: true when s fails to match at least one
+query T rowsort
+SELECT s FROM test WHERE s NOT LIKE ANY ('p%', '%e1');
+----
+P1
+P1e1
+P1m1e1
+e1
+p1
+p2
+
+# NOT before the subject negates the whole match
+query T rowsort
+SELECT s FROM test WHERE NOT s LIKE ANY ('p%', '%e1');
+----
+P1
+
+# ILIKE ANY
+query T rowsort
+SELECT s FROM test WHERE s ILIKE ANY ('p1', 'E%');
+----
+P1
+e1
+p1
+
+query T rowsort
+SELECT s FROM test WHERE s NOT ILIKE ANY ('p%', '%e1');
+----
+P1
+e1
+p1
+p2
+
+query B
+SELECT 'a_c' LIKE ANY ('a\_c', 'x%') ESCAPE '\';
+----
+true
+
+# ESCAPE applies to every pattern
+query TT
+EXPLAIN SELECT s FROM test WHERE s LIKE ANY ('p\_%', '%e1') ESCAPE '\';
+----
+logical_plan
+01)Filter: test.s LIKE Utf8View("p\_%") ESCAPE '\' OR test.s LIKE 
Utf8View("%e1") ESCAPE '\'
+02)--TableScan: test projection=[s]
+physical_plan
+01)FilterExec: s@0 LIKE p\_% OR s@0 LIKE %e1
+02)--DataSourceExec: partitions=1, partition_sizes=[1]
+
+# A NULL pattern gives NULL only when no other pattern matches
+query BBBB
+SELECT 'ab' LIKE ANY ('a%', NULL), 'ab' LIKE ANY ('x%', NULL), 'ab' LIKE ANY 
('x%', 'y%'), NULL LIKE ANY ('a%', 'c%');
+----
+true NULL false NULL
+
+query BBB
+SELECT 'ab' NOT LIKE ANY ('a%', 'c%'), 'ab' NOT LIKE ANY ('a%', '%b'), NOT 
'ab' LIKE ANY ('a%', 'c%');

Review Comment:
   Could we optionally add NULL cases for negation? For example, `'ab' NOT LIKE 
ANY ('a%', NULL)` should return NULL, `'ab' NOT LIKE ANY ('x%', NULL)` should 
return true, and `NOT 'ab' LIKE ANY ('a%', NULL)` should return false. Existing 
tests cover these behaviors separately, but combining them would strengthen 
regression coverage.



##########
docs/source/user-guide/sql/operators.md:
##########
@@ -617,6 +619,89 @@ applies the opposite (POSIX) convention to offsets spelled 
this way.
 
 [`timezone(tz, expression)`]: scalar_functions.md#timezone
 
+(op_like_any)=
+
+### `LIKE ANY`
+
+Like Any: `expression LIKE ANY (pattern1, ..., patternN)` is true when
+`expression` matches at least one pattern. It is the same as
+`expression LIKE pattern1 OR ... OR expression LIKE patternN`, following Spark.
+
+```sql
+> SELECT 'datafusion' LIKE ANY ('dat%', '%sql') AS like_any;
++----------+
+| like_any |
++----------+
+| true     |
++----------+
+```
+
+`NOT` before `LIKE` applies to each pattern, so `expression NOT LIKE ANY (...)`
+is true when `expression` fails to match at least one pattern. `NOT` before the
+expression negates the whole match:
+
+```sql
+> SELECT
+  'datafusion' NOT LIKE ANY ('dat%', '%sql') AS per_pattern,
+  NOT 'datafusion' LIKE ANY ('dat%', '%sql') AS whole_match;
++-------------+-------------+
+| per_pattern | whole_match |
++-------------+-------------+
+| true        | false       |
++-------------+-------------+
+```
+
+An `ESCAPE` character applies to every pattern:
+
+```sql
+> SELECT 'data_fusion' LIKE ANY ('data\_%', '%sql') ESCAPE '\' AS escaped;
++---------+
+| escaped |
++---------+
+| true    |
++---------+
+```
+
+A NULL pattern gives NULL only when no other pattern matches. A NULL
+expression gives NULL:
+
+```sql
+> SELECT
+  'datafusion' LIKE ANY ('dat%', NULL) AS one_match,
+  'datafusion' LIKE ANY ('%sql', NULL) AS no_match,
+  NULL LIKE ANY ('dat%', '%sql') AS null_subject;
++-----------+----------+--------------+
+| one_match | no_match | null_subject |
++-----------+----------+--------------+
+| true      | NULL     | NULL         |
++-----------+----------+--------------+
+```
+
+Snowflake differs here: its `LIKE ANY` returns NULL when any argument is NULL,
+so `'datafusion' LIKE ANY ('dat%', NULL)` is NULL in Snowflake.
+
+The patterns must be a parenthesized list. An array of patterns, such as
+`ARRAY['dat%', '%sql']` or `make_array('dat%', '%sql')`, and a subquery are not
+supported. A volatile expression, such as `CAST(random() AS VARCHAR)`, is not

Review Comment:
   Could we clarify that the volatility restriction applies specifically to the 
left-hand expression, not the patterns, and that the unsupported subquery form 
is a subquery supplying the pattern list? Nonvolatile scalar-subquery subjects 
are supported, so the current wording could imply broader restrictions than the 
planner enforces.



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