Skip to main content

arrow_string/
like.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! String predicate kernels for Arrow arrays.
19//!
20//! Provides SQL `LIKE`/`ILIKE` kernels as well as related
21//! string predicates such as `contains`, `starts_with`, `ends_with`, and
22//! ASCII case-insensitive equality.
23
24use crate::predicate::Predicate;
25
26use arrow_array::cast::AsArray;
27use arrow_array::*;
28use arrow_schema::*;
29use arrow_select::take::take;
30
31use crate::binary_like::binary_apply;
32pub use arrow_array::StringArrayType;
33
34#[derive(Debug)]
35pub(crate) enum Op {
36    Like(bool),
37    ILike(bool),
38    Contains,
39    EqIgnoreAsciiCase,
40    StartsWith,
41    EndsWith,
42}
43
44impl std::fmt::Display for Op {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        match self {
47            Op::Like(false) => write!(f, "LIKE"),
48            Op::Like(true) => write!(f, "NLIKE"),
49            Op::ILike(false) => write!(f, "ILIKE"),
50            Op::ILike(true) => write!(f, "NILIKE"),
51            Op::Contains => write!(f, "CONTAINS"),
52            Op::EqIgnoreAsciiCase => write!(f, "EQ_IGNORE_ASCII_CASE"),
53            Op::StartsWith => write!(f, "STARTS_WITH"),
54            Op::EndsWith => write!(f, "ENDS_WITH"),
55        }
56    }
57}
58
59/// Perform SQL `left LIKE right`
60///
61/// # Supported DataTypes
62///
63/// `left` and `right` must be the same type, and one of
64/// - Utf8
65/// - LargeUtf8
66/// - Utf8View
67///
68/// There are two wildcards supported with the LIKE operator:
69///
70/// 1. `%` - The percent sign represents zero, one, or multiple characters
71/// 2. `_` - The underscore represents a single character
72///
73/// Example
74/// ```
75/// # use arrow_array::{StringArray, BooleanArray};
76/// # use arrow_string::like::like;
77/// let strings = StringArray::from(vec!["Arrow", "Arrow", "Arrow", "Ar"]);
78/// let patterns = StringArray::from(vec!["A%", "B%", "A.", "A_"]);
79///
80/// let result = like(&strings, &patterns).unwrap();
81/// assert_eq!(result, BooleanArray::from(vec![true, false, false, true]));
82/// ```
83pub fn like(left: &dyn Datum, right: &dyn Datum) -> Result<BooleanArray, ArrowError> {
84    like_op(Op::Like(false), left, right)
85}
86
87/// Perform SQL `left ILIKE right`
88///
89/// # Notes
90/// - This is a case-insensitive version of [`like`]
91/// - See the documentation on [`like`] for more details
92/// - Implements loose matching as defined by the Unicode standard. For example,
93///   the `ff` ligature is not equivalent to `FF` and `ß` is not equivalent to `SS`
94pub fn ilike(left: &dyn Datum, right: &dyn Datum) -> Result<BooleanArray, ArrowError> {
95    like_op(Op::ILike(false), left, right)
96}
97
98/// Perform SQL `left NOT LIKE right`
99///
100/// # Notes
101/// - This is a negative of [`like`]
102/// - See the documentation on [`like`] for more details
103pub fn nlike(left: &dyn Datum, right: &dyn Datum) -> Result<BooleanArray, ArrowError> {
104    like_op(Op::Like(true), left, right)
105}
106
107/// Perform SQL `left NOT ILIKE right`
108///
109/// # Notes
110/// - This is a negative of [`like`]
111/// - See the documentation on [`ilike`] for more details
112pub fn nilike(left: &dyn Datum, right: &dyn Datum) -> Result<BooleanArray, ArrowError> {
113    like_op(Op::ILike(true), left, right)
114}
115
116/// Perform SQL `STARTSWITH(left, right)`
117///
118/// # Supported DataTypes
119///
120/// `left` and `right` must be the same type, and one of
121/// - Utf8
122/// - LargeUtf8
123/// - Utf8View
124/// - Binary
125/// - LargeBinary
126/// - BinaryView
127///
128/// # Example
129/// ```
130/// # use arrow_array::{StringArray, BooleanArray};
131/// # use arrow_string::like::starts_with;
132/// let strings = StringArray::from(vec!["arrow-rs", "arrow-rs", "arrow-rs", "Parquet"]);
133/// let patterns = StringArray::from(vec!["arr", "arrow", "arrow-cpp", "p"]);
134///
135/// let result = starts_with(&strings, &patterns).unwrap();
136/// assert_eq!(result, BooleanArray::from(vec![true, true, false, false]));
137/// ```
138pub fn starts_with(left: &dyn Datum, right: &dyn Datum) -> Result<BooleanArray, ArrowError> {
139    like_op(Op::StartsWith, left, right)
140}
141
142/// Perform SQL `ENDSWITH(left, right)`
143///
144/// # Supported DataTypes
145///
146/// `left` and `right` must be the same type, and one of
147/// - Utf8
148/// - LargeUtf8
149/// - Utf8View
150/// - Binary
151/// - LargeBinary
152/// - BinaryView
153///
154/// # Example
155/// ```
156/// # use arrow_array::{StringArray, BooleanArray};
157/// # use arrow_string::like::ends_with;
158/// let strings = StringArray::from(vec!["arrow-rs", "arrow-rs",  "Parquet"]);
159/// let patterns = StringArray::from(vec!["arr", "-rs", "t"]);
160///
161/// let result = ends_with(&strings, &patterns).unwrap();
162/// assert_eq!(result, BooleanArray::from(vec![false, true, true]));
163/// ```
164pub fn ends_with(left: &dyn Datum, right: &dyn Datum) -> Result<BooleanArray, ArrowError> {
165    like_op(Op::EndsWith, left, right)
166}
167
168/// Perform SQL `CONTAINS(left, right)`
169///
170/// # Supported DataTypes
171///
172/// `left` and `right` must be the same type, and one of
173/// - Utf8
174/// - LargeUtf8
175/// - Utf8View
176/// - Binary
177/// - LargeBinary
178/// - BinaryView
179///
180/// # Example
181/// ```
182/// # use arrow_array::{StringArray, BooleanArray};
183/// # use arrow_string::like::contains;
184/// let strings = StringArray::from(vec!["arrow-rs", "arrow-rs", "arrow-rs", "Parquet"]);
185/// let patterns = StringArray::from(vec!["arr", "-rs", "arrow-cpp", "X"]);
186///
187/// let result = contains(&strings, &patterns).unwrap();
188/// assert_eq!(result, BooleanArray::from(vec![true, true, false, false]));
189/// ```
190pub fn contains(left: &dyn Datum, right: &dyn Datum) -> Result<BooleanArray, ArrowError> {
191    like_op(Op::Contains, left, right)
192}
193
194/// Perform equality check on two arrays using an ASCII case-insensitive match.
195///
196/// `left` and `right` must be the same type, and one of
197/// - Utf8
198/// - LargeUtf8
199/// - Utf8View
200///
201/// # Example
202/// ```
203/// # use arrow_array::{StringArray, BooleanArray};
204/// # use arrow_string::like::eq_ignore_ascii_case;
205/// let strings = StringArray::from(vec!["arrow", "rs", "arrow-rS", "Parquet"]);
206/// let patterns = StringArray::from(vec!["ARROW", "rS", "ARROW-rs", "arrow"]);
207///
208/// let result = eq_ignore_ascii_case(&strings, &patterns).unwrap();
209/// assert_eq!(result, BooleanArray::from(vec![true, true, true, false]));
210/// ```
211pub fn eq_ignore_ascii_case(
212    left: &dyn Datum,
213    right: &dyn Datum,
214) -> Result<BooleanArray, ArrowError> {
215    like_op(Op::EqIgnoreAsciiCase, left, right)
216}
217
218fn like_op(op: Op, lhs: &dyn Datum, rhs: &dyn Datum) -> Result<BooleanArray, ArrowError> {
219    use arrow_schema::DataType::*;
220    let (l, l_s) = lhs.get();
221    let (r, r_s) = rhs.get();
222
223    if l.len() != r.len() && !l_s && !r_s {
224        return Err(ArrowError::InvalidArgumentError(format!(
225            "Cannot compare arrays of different lengths, got {} vs {}",
226            l.len(),
227            r.len()
228        )));
229    }
230
231    let l_v = l.as_any_dictionary_opt();
232    let l = l_v.map(|x| x.values().as_ref()).unwrap_or(l);
233
234    let r_v = r.as_any_dictionary_opt();
235    let r = r_v.map(|x| x.values().as_ref()).unwrap_or(r);
236
237    match (l.data_type(), r.data_type()) {
238        (Utf8, Utf8) => string_apply::<&GenericStringArray<i32>>(
239            op,
240            l.as_string(),
241            l_s,
242            l_v,
243            r.as_string(),
244            r_s,
245            r_v,
246        ),
247        (LargeUtf8, LargeUtf8) => string_apply::<&GenericStringArray<i64>>(
248            op,
249            l.as_string(),
250            l_s,
251            l_v,
252            r.as_string(),
253            r_s,
254            r_v,
255        ),
256        (Utf8View, Utf8View) => string_apply::<&StringViewArray>(
257            op,
258            l.as_string_view(),
259            l_s,
260            l_v,
261            r.as_string_view(),
262            r_s,
263            r_v,
264        ),
265        (Binary, Binary) => binary_apply::<&GenericBinaryArray<i32>>(
266            op.try_into()?,
267            l.as_binary(),
268            l_s,
269            l_v,
270            r.as_binary(),
271            r_s,
272            r_v,
273        ),
274        (LargeBinary, LargeBinary) => binary_apply::<&GenericBinaryArray<i64>>(
275            op.try_into()?,
276            l.as_binary(),
277            l_s,
278            l_v,
279            r.as_binary(),
280            r_s,
281            r_v,
282        ),
283        (BinaryView, BinaryView) => binary_apply::<&BinaryViewArray>(
284            op.try_into()?,
285            l.as_binary_view(),
286            l_s,
287            l_v,
288            r.as_binary_view(),
289            r_s,
290            r_v,
291        ),
292        (l_t, r_t) => Err(ArrowError::InvalidArgumentError(format!(
293            "Invalid string/binary operation: {l_t} {op} {r_t}"
294        ))),
295    }
296}
297
298fn string_apply<'a, T: StringArrayType<'a> + 'a>(
299    op: Op,
300    l: T,
301    l_s: bool,
302    l_v: Option<&'a dyn AnyDictionaryArray>,
303    r: T,
304    r_s: bool,
305    r_v: Option<&'a dyn AnyDictionaryArray>,
306) -> Result<BooleanArray, ArrowError> {
307    let l_len = l_v.map(|l| l.len()).unwrap_or(l.len());
308    if r_s {
309        let idx = match r_v {
310            Some(dict) if dict.null_count() != 0 => return Ok(BooleanArray::new_null(l_len)),
311            Some(dict) => dict.normalized_keys()[0],
312            None => 0,
313        };
314        if r.is_null(idx) {
315            return Ok(BooleanArray::new_null(l_len));
316        }
317        op_scalar::<T>(op, l, l_v, r.value(idx))
318    } else {
319        match (l_s, l_v, r_v) {
320            (true, None, None) => {
321                let v = l.is_valid(0).then(|| l.value(0));
322                op_binary(op, std::iter::repeat(v), r.iter())
323            }
324            (true, Some(l_v), None) => {
325                let idx = l_v.is_valid(0).then(|| l_v.normalized_keys()[0]);
326                let v = idx.and_then(|idx| l.is_valid(idx).then(|| l.value(idx)));
327                op_binary(op, std::iter::repeat(v), r.iter())
328            }
329            (true, None, Some(r_v)) => {
330                let v = l.is_valid(0).then(|| l.value(0));
331                op_binary(op, std::iter::repeat(v), vectored_iter(r, r_v))
332            }
333            (true, Some(l_v), Some(r_v)) => {
334                let idx = l_v.is_valid(0).then(|| l_v.normalized_keys()[0]);
335                let v = idx.and_then(|idx| l.is_valid(idx).then(|| l.value(idx)));
336                op_binary(op, std::iter::repeat(v), vectored_iter(r, r_v))
337            }
338            (false, None, None) => op_binary(op, l.iter(), r.iter()),
339            (false, Some(l_v), None) => op_binary(op, vectored_iter(l, l_v), r.iter()),
340            (false, None, Some(r_v)) => op_binary(op, l.iter(), vectored_iter(r, r_v)),
341            (false, Some(l_v), Some(r_v)) => {
342                op_binary(op, vectored_iter(l, l_v), vectored_iter(r, r_v))
343            }
344        }
345    }
346}
347
348#[inline(never)]
349fn op_scalar<'a, T: StringArrayType<'a>>(
350    op: Op,
351    l: T,
352    l_v: Option<&dyn AnyDictionaryArray>,
353    r: &str,
354) -> Result<BooleanArray, ArrowError> {
355    let r = match op {
356        Op::Like(neg) => Predicate::like(r)?.evaluate_array(l, neg),
357        Op::ILike(neg) => Predicate::ilike(r, l.is_ascii())?.evaluate_array(l, neg),
358        Op::Contains => Predicate::contains(r).evaluate_array(l, false),
359        Op::EqIgnoreAsciiCase => Predicate::IEqAscii(r).evaluate_array(l, false),
360        Op::StartsWith => Predicate::StartsWith(r).evaluate_array(l, false),
361        Op::EndsWith => Predicate::EndsWith(r).evaluate_array(l, false),
362    };
363
364    Ok(match l_v {
365        Some(v) => take(&r, v.keys(), None)?.as_boolean().clone(),
366        None => r,
367    })
368}
369
370fn vectored_iter<'a, T: StringArrayType<'a> + 'a>(
371    a: T,
372    a_v: &'a dyn AnyDictionaryArray,
373) -> impl Iterator<Item = Option<&'a str>> + 'a {
374    let nulls = a_v.nulls();
375    let keys = a_v.normalized_keys();
376    keys.into_iter().enumerate().map(move |(idx, key)| {
377        if nulls.is_some_and(|n| n.is_null(idx)) || a.is_null(key) {
378            return None;
379        }
380        Some(a.value(key))
381    })
382}
383
384#[inline(never)]
385fn op_binary<'a>(
386    op: Op,
387    l: impl Iterator<Item = Option<&'a str>>,
388    r: impl Iterator<Item = Option<&'a str>>,
389) -> Result<BooleanArray, ArrowError> {
390    match op {
391        Op::Like(neg) => binary_predicate(l, r, neg, Predicate::like),
392        Op::ILike(neg) => binary_predicate(l, r, neg, |s| Predicate::ilike(s, false)),
393        Op::Contains => Ok(l.zip(r).map(|(l, r)| Some(str_contains(l?, r?))).collect()),
394        Op::EqIgnoreAsciiCase => Ok(l
395            .zip(r)
396            .map(|(l, r)| Some(Predicate::IEqAscii(l?).evaluate(r?)))
397            .collect()),
398        Op::StartsWith => Ok(l
399            .zip(r)
400            .map(|(l, r)| Some(Predicate::StartsWith(r?).evaluate(l?)))
401            .collect()),
402        Op::EndsWith => Ok(l
403            .zip(r)
404            .map(|(l, r)| Some(Predicate::EndsWith(r?).evaluate(l?)))
405            .collect()),
406    }
407}
408
409fn str_contains(haystack: &str, needle: &str) -> bool {
410    memchr::memmem::find(haystack.as_bytes(), needle.as_bytes()).is_some()
411}
412
413fn binary_predicate<'a>(
414    l: impl Iterator<Item = Option<&'a str>>,
415    r: impl Iterator<Item = Option<&'a str>>,
416    neg: bool,
417    f: impl Fn(&'a str) -> Result<Predicate<'a>, ArrowError>,
418) -> Result<BooleanArray, ArrowError> {
419    let mut previous = None;
420    l.zip(r)
421        .map(|(l, r)| match (l, r) {
422            (Some(l), Some(r)) => {
423                let p: &Predicate = match previous {
424                    Some((expr, ref predicate)) if expr == r => predicate,
425                    _ => &previous.insert((r, f(r)?)).1,
426                };
427                Ok(Some(p.evaluate(l) != neg))
428            }
429            _ => Ok(None),
430        })
431        .collect()
432}
433
434#[cfg(test)]
435mod tests {
436    use super::*;
437    use arrow_array::builder::BinaryDictionaryBuilder;
438    use arrow_array::types::{ArrowDictionaryKeyType, Int8Type};
439    use std::iter::zip;
440
441    fn convert_binary_iterator_to_binary_dictionary<
442        'a,
443        K: ArrowDictionaryKeyType,
444        I: IntoIterator<Item = &'a [u8]>,
445    >(
446        iter: I,
447    ) -> DictionaryArray<K> {
448        let it = iter.into_iter();
449        let (lower, _) = it.size_hint();
450        let mut builder = BinaryDictionaryBuilder::with_capacity(lower, 256, 1024);
451        it.for_each(|i| {
452            builder
453                .append(i)
454                .expect("Unable to append a value to a dictionary array.");
455        });
456
457        builder.finish()
458    }
459
460    /// Applying `op(left, right)`, both sides are arrays
461    /// The macro tests four types of array implementations:
462    /// - `StringArray`
463    /// - `LargeStringArray`
464    /// - `StringViewArray`
465    /// - `DictionaryArray`
466    macro_rules! test_utf8 {
467        ($(#[$attr:meta])* $test_name:ident, $left:expr, $right:expr, $op:expr, $expected:expr) => {
468            $(#[$attr])*
469            #[test]
470            fn $test_name() {
471                let expected = BooleanArray::from($expected);
472
473                let left = StringArray::from($left);
474                let right = StringArray::from($right);
475                let res = $op(&left, &right).unwrap();
476                assert_eq!(res, expected);
477
478                let left = LargeStringArray::from($left);
479                let right = LargeStringArray::from($right);
480                let res = $op(&left, &right).unwrap();
481                assert_eq!(res, expected);
482
483                let left = StringViewArray::from($left);
484                let right = StringViewArray::from($right);
485                let res = $op(&left, &right).unwrap();
486                assert_eq!(res, expected);
487
488                let left: DictionaryArray<Int8Type> = $left.into_iter().collect();
489                let right: DictionaryArray<Int8Type> = $right.into_iter().collect();
490                let res = $op(&left, &right).unwrap();
491                assert_eq!(res, expected);
492            }
493        };
494    }
495
496    /// Applying `op(left, right)`, both sides are arrays
497    /// The macro tests four types of array implementations:
498    /// - `StringArray`
499    /// - `LargeStringArray`
500    /// - `StringViewArray`
501    /// - `DictionaryArray`
502    macro_rules! test_utf8_and_binary {
503        ($test_name:ident, $left:expr, $right:expr, $op:expr, $expected:expr) => {
504            #[test]
505            fn $test_name() {
506                let expected = BooleanArray::from($expected);
507
508                let left = StringArray::from($left);
509                let right = StringArray::from($right);
510                let res = $op(&left, &right).unwrap();
511                assert_eq!(res, expected);
512
513                let left = LargeStringArray::from($left);
514                let right = LargeStringArray::from($right);
515                let res = $op(&left, &right).unwrap();
516                assert_eq!(res, expected);
517
518                let left = StringViewArray::from($left);
519                let right = StringViewArray::from($right);
520                let res = $op(&left, &right).unwrap();
521                assert_eq!(res, expected);
522
523                let left: DictionaryArray<Int8Type> = $left.into_iter().collect();
524                let right: DictionaryArray<Int8Type> = $right.into_iter().collect();
525                let res = $op(&left, &right).unwrap();
526                assert_eq!(res, expected);
527
528                let left_binary = $left.iter().map(|x| x.as_bytes()).collect::<Vec<&[u8]>>();
529                let right_binary = $right.iter().map(|x| x.as_bytes()).collect::<Vec<&[u8]>>();
530
531                let left = BinaryArray::from(left_binary.clone());
532                let right = BinaryArray::from(right_binary.clone());
533                let res = $op(&left, &right).unwrap();
534                assert_eq!(res, expected);
535
536                let left = LargeBinaryArray::from(left_binary.clone());
537                let right = LargeBinaryArray::from(right_binary.clone());
538                let res = $op(&left, &right).unwrap();
539                assert_eq!(res, expected);
540
541                let left: DictionaryArray<Int8Type> =
542                    convert_binary_iterator_to_binary_dictionary(left_binary);
543                let right: DictionaryArray<Int8Type> =
544                    convert_binary_iterator_to_binary_dictionary(right_binary);
545                let res = $op(&left, &right).unwrap();
546                assert_eq!(res, expected);
547            }
548        };
549    }
550
551    /// Applying `op(left, right)`, left side is array, right side is scalar
552    /// The macro tests four types of array implementations:
553    /// - `StringArray`
554    /// - `LargeStringArray`
555    /// - `StringViewArray`
556    /// - `DictionaryArray`
557    macro_rules! test_utf8_scalar {
558        ($(#[$attr:meta])* $test_name:ident, $left:expr, $right:expr, $op:expr, $expected:expr) => {
559            $(#[$attr])*
560            #[test]
561            fn $test_name() {
562                let expected = BooleanArray::from($expected);
563
564                let left = StringArray::from($left);
565                let right = StringArray::from_iter_values([$right]);
566                let res = $op(&left, &Scalar::new(&right)).unwrap();
567                assert_eq!(res, expected);
568
569                let left = LargeStringArray::from($left);
570                let right = LargeStringArray::from_iter_values([$right]);
571                let res = $op(&left, &Scalar::new(&right)).unwrap();
572                assert_eq!(res, expected);
573
574                let left = StringViewArray::from($left);
575                let right = StringViewArray::from_iter_values([$right]);
576                let res = $op(&left, &Scalar::new(&right)).unwrap();
577                assert_eq!(res, expected);
578
579                let left: DictionaryArray<Int8Type> = $left.into_iter().collect();
580                let right = StringArray::from_iter_values([$right]);
581                let res = $op(&left, &Scalar::new(&right)).unwrap();
582                assert_eq!(res, expected);
583
584                let right: DictionaryArray<Int8Type> = [$right].into_iter().collect();
585                let res = $op(&left, &Scalar::new(&right)).unwrap();
586                assert_eq!(res, expected);
587            }
588        };
589    }
590
591    /// Applying `op(left, right)`, left side is array, right side is scalar
592    /// The macro tests four types of array implementations:
593    /// - `StringArray`
594    /// - `LargeStringArray`
595    /// - `StringViewArray`
596    /// - `DictionaryArray`
597    macro_rules! test_utf8_and_binary_scalar {
598        ($test_name:ident, $left:expr, $right:expr, $op:expr, $expected:expr) => {
599            #[test]
600            fn $test_name() {
601                let expected = BooleanArray::from($expected);
602
603                let left = StringArray::from($left);
604                let right = StringArray::from_iter_values([$right]);
605                let res = $op(&left, &Scalar::new(&right)).unwrap();
606                assert_eq!(res, expected);
607
608                let left = LargeStringArray::from($left);
609                let right = LargeStringArray::from_iter_values([$right]);
610                let res = $op(&left, &Scalar::new(&right)).unwrap();
611                assert_eq!(res, expected);
612
613                let left = StringViewArray::from($left);
614                let right = StringViewArray::from_iter_values([$right]);
615                let res = $op(&left, &Scalar::new(&right)).unwrap();
616                assert_eq!(res, expected);
617
618                let left: DictionaryArray<Int8Type> = $left.into_iter().collect();
619                let right: DictionaryArray<Int8Type> = [$right].into_iter().collect();
620                let res = $op(&left, &Scalar::new(&right)).unwrap();
621                assert_eq!(res, expected);
622
623                let left_binary = $left.iter().map(|x| x.as_bytes()).collect::<Vec<&[u8]>>();
624                let right_binary = $right.as_bytes();
625
626                let left = BinaryArray::from(left_binary.clone());
627                let right = BinaryArray::from_iter_values([right_binary]);
628                let res = $op(&left, &Scalar::new(&right)).unwrap();
629                assert_eq!(res, expected);
630
631                let left = LargeBinaryArray::from(left_binary.clone());
632                let right = LargeBinaryArray::from_iter_values([right_binary]);
633                let res = $op(&left, &Scalar::new(&right)).unwrap();
634                assert_eq!(res, expected);
635
636                let left: DictionaryArray<Int8Type> =
637                    convert_binary_iterator_to_binary_dictionary(left_binary);
638                let right: DictionaryArray<Int8Type> =
639                    convert_binary_iterator_to_binary_dictionary([right_binary]);
640                let res = $op(&left, &Scalar::new(&right)).unwrap();
641                assert_eq!(res, expected);
642            }
643        };
644    }
645
646    test_utf8!(
647        test_utf8_array_like,
648        vec![
649            "arrow",
650            "arrow_long_string_more than 12 bytes",
651            "arrow",
652            "arrow",
653            "arrow",
654            "arrows",
655            "arrow",
656            "arrow"
657        ],
658        vec![
659            "arrow", "ar%", "%ro%", "foo", "arr", "arrow_", "arrow_", ".*"
660        ],
661        like,
662        vec![true, true, true, false, false, true, false, false]
663    );
664
665    test_utf8_scalar!(
666        #[cfg_attr(miri, ignore)] // Takes too long
667        test_utf8_array_like_scalar_escape_testing,
668        vec![
669            "varchar(255)",
670            "int(255)longer than 12 bytes",
671            "varchar",
672            "int"
673        ],
674        "%(%)%",
675        like,
676        vec![true, true, false, false]
677    );
678
679    test_utf8_scalar!(
680        test_utf8_array_like_scalar_escape_regex,
681        vec![".*", "a", "*"],
682        ".*",
683        like,
684        vec![true, false, false]
685    );
686
687    test_utf8_scalar!(
688        test_utf8_array_like_scalar_escape_regex_dot,
689        vec![".", "a", "*"],
690        ".",
691        like,
692        vec![true, false, false]
693    );
694
695    test_utf8_scalar!(
696        test_utf8_array_like_scalar,
697        vec![
698            "arrow",
699            "parquet",
700            "datafusion",
701            "flight",
702            "long string arrow test 12 bytes"
703        ],
704        "%ar%",
705        like,
706        vec![true, true, false, false, true]
707    );
708
709    test_utf8_scalar!(
710        test_utf8_array_like_scalar_start,
711        vec![
712            "arrow",
713            "parrow",
714            "arrows",
715            "arr",
716            "arrow long string longer than 12 bytes"
717        ],
718        "arrow%",
719        like,
720        vec![true, false, true, false, true]
721    );
722
723    // Replicates `test_utf8_array_like_scalar_start` `test_utf8_array_like_scalar_dyn_start` to
724    // demonstrate that `SQL STARTSWITH` works as expected.
725    test_utf8_and_binary_scalar!(
726        test_utf8_and_binary_array_starts_with_scalar_start,
727        vec![
728            "arrow",
729            "parrow",
730            "arrows",
731            "arr",
732            "arrow long string longer than 12 bytes"
733        ],
734        "arrow",
735        starts_with,
736        vec![true, false, true, false, true]
737    );
738
739    test_utf8_and_binary!(
740        test_utf8_and_binary_array_starts_with,
741        vec![
742            "arrow",
743            "arrow_long_string_more than 12 bytes",
744            "arrow",
745            "arrow",
746            "arrow",
747            "arrows",
748            "arrow",
749            "arrow"
750        ],
751        vec![
752            "arrow", "ar%", "row", "foo", "arr", "arrow_", "arrow_", ".*"
753        ],
754        starts_with,
755        vec![true, false, false, false, true, false, false, false]
756    );
757
758    test_utf8_scalar!(
759        test_utf8_array_like_scalar_end,
760        vec![
761            "arrow",
762            "parrow",
763            "arrows",
764            "arr",
765            "arrow long string longer than 12 bytes"
766        ],
767        "%arrow",
768        like,
769        vec![true, true, false, false, false]
770    );
771
772    // Replicates `test_utf8_array_like_scalar_end` `test_utf8_array_like_scalar_dyn_end` to
773    // demonstrate that `SQL ENDSWITH` works as expected.
774    test_utf8_and_binary_scalar!(
775        test_utf8_and_binary_array_ends_with_scalar_end,
776        vec![
777            "arrow",
778            "parrow",
779            "arrows",
780            "arr",
781            "arrow long string longer than 12 bytes"
782        ],
783        "arrow",
784        ends_with,
785        vec![true, true, false, false, false]
786    );
787
788    test_utf8_and_binary!(
789        test_utf8_and_binary_array_ends_with,
790        vec![
791            "arrow",
792            "arrow_long_string_more than 12 bytes",
793            "arrow",
794            "arrow",
795            "arrow",
796            "arrows",
797            "arrow",
798            "arrow"
799        ],
800        vec![
801            "arrow", "ar%", "row", "foo", "arr", "arrow_", "arrow_", ".*"
802        ],
803        ends_with,
804        vec![true, false, true, false, false, false, false, false]
805    );
806
807    test_utf8_scalar!(
808        test_utf8_array_like_scalar_equals,
809        vec![
810            "arrow",
811            "parrow",
812            "arrows",
813            "arr",
814            "arrow long string longer than 12 bytes"
815        ],
816        "arrow",
817        like,
818        vec![true, false, false, false, false]
819    );
820
821    test_utf8_scalar!(
822        #[cfg_attr(miri, ignore)] // Takes too long
823        test_utf8_array_like_scalar_one,
824        vec![
825            "arrow",
826            "arrows",
827            "parrow",
828            "arr",
829            "arrow long string longer than 12 bytes"
830        ],
831        "arrow_",
832        like,
833        vec![false, true, false, false, false]
834    );
835
836    test_utf8_scalar!(
837        test_utf8_scalar_like_escape,
838        vec!["a%", "a\\x", "arrow long string longer than 12 bytes"],
839        "a\\%",
840        like,
841        vec![true, false, false]
842    );
843
844    test_utf8_scalar!(
845        test_utf8_scalar_like_escape_contains,
846        vec!["ba%", "ba\\x", "arrow long string longer than 12 bytes"],
847        "%a\\%",
848        like,
849        vec![true, false, false]
850    );
851
852    test_utf8!(
853        test_utf8_scalar_ilike_regex,
854        vec!["%%%"],
855        vec![r"\%_\%"],
856        ilike,
857        vec![true]
858    );
859
860    test_utf8!(
861        test_utf8_array_nlike,
862        vec![
863            "arrow",
864            "arrow",
865            "arrow long string longer than 12 bytes",
866            "arrow",
867            "arrow",
868            "arrows",
869            "arrow"
870        ],
871        vec!["arrow", "ar%", "%ro%", "foo", "arr", "arrow_", "arrow_"],
872        nlike,
873        vec![false, false, false, true, true, false, true]
874    );
875
876    test_utf8_scalar!(
877        #[cfg_attr(miri, ignore)] // Takes too long
878        test_utf8_array_nlike_escape_testing,
879        vec![
880            "varchar(255)",
881            "int(255) arrow long string longer than 12 bytes",
882            "varchar",
883            "int"
884        ],
885        "%(%)%",
886        nlike,
887        vec![false, false, true, true]
888    );
889
890    test_utf8_scalar!(
891        test_utf8_array_nlike_scalar_escape_regex,
892        vec![".*", "a", "*"],
893        ".*",
894        nlike,
895        vec![false, true, true]
896    );
897
898    test_utf8_scalar!(
899        test_utf8_array_nlike_scalar_escape_regex_dot,
900        vec![".", "a", "*"],
901        ".",
902        nlike,
903        vec![false, true, true]
904    );
905    test_utf8_scalar!(
906        test_utf8_array_nlike_scalar,
907        vec![
908            "arrow",
909            "parquet",
910            "datafusion",
911            "flight",
912            "arrow long string longer than 12 bytes"
913        ],
914        "%ar%",
915        nlike,
916        vec![false, false, true, true, false]
917    );
918
919    test_utf8_scalar!(
920        test_utf8_array_nlike_scalar_start,
921        vec![
922            "arrow",
923            "parrow",
924            "arrows",
925            "arr",
926            "arrow long string longer than 12 bytes"
927        ],
928        "arrow%",
929        nlike,
930        vec![false, true, false, true, false]
931    );
932
933    test_utf8_scalar!(
934        test_utf8_array_nlike_scalar_end,
935        vec![
936            "arrow",
937            "parrow",
938            "arrows",
939            "arr",
940            "arrow long string longer than 12 bytes"
941        ],
942        "%arrow",
943        nlike,
944        vec![false, false, true, true, true]
945    );
946
947    test_utf8_scalar!(
948        test_utf8_array_nlike_scalar_equals,
949        vec![
950            "arrow",
951            "parrow",
952            "arrows",
953            "arr",
954            "arrow long string longer than 12 bytes"
955        ],
956        "arrow",
957        nlike,
958        vec![false, true, true, true, true]
959    );
960
961    test_utf8_scalar!(
962        #[cfg_attr(miri, ignore)] // Takes too long
963        test_utf8_array_nlike_scalar_one,
964        vec![
965            "arrow",
966            "arrows",
967            "parrow",
968            "arr",
969            "arrow long string longer than 12 bytes"
970        ],
971        "arrow_",
972        nlike,
973        vec![true, false, true, true, true]
974    );
975
976    test_utf8!(
977        #[cfg_attr(miri, ignore)] // Takes too long
978        test_utf8_array_ilike,
979        vec![
980            "arrow",
981            "arrow",
982            "ARROW long string longer than 12 bytes",
983            "arrow",
984            "ARROW",
985            "ARROWS",
986            "arROw"
987        ],
988        vec!["arrow", "ar%", "%ro%", "foo", "ar%r", "arrow_", "arrow_"],
989        ilike,
990        vec![true, true, true, false, false, true, false]
991    );
992
993    test_utf8_scalar!(
994        #[cfg_attr(miri, ignore)] // Takes too long
995        ilike_utf8_scalar_escape_testing,
996        vec![
997            "varchar(255)",
998            "int(255) long string longer than 12 bytes",
999            "varchar",
1000            "int"
1001        ],
1002        "%(%)%",
1003        ilike,
1004        vec![true, true, false, false]
1005    );
1006
1007    test_utf8_scalar!(
1008        test_utf8_array_ilike_scalar,
1009        vec![
1010            "arrow",
1011            "parquet",
1012            "datafusion",
1013            "flight",
1014            "arrow long string longer than 12 bytes"
1015        ],
1016        "%AR%",
1017        ilike,
1018        vec![true, true, false, false, true]
1019    );
1020
1021    test_utf8_scalar!(
1022        test_utf8_array_ilike_scalar_start,
1023        vec![
1024            "arrow",
1025            "parrow",
1026            "arrows",
1027            "ARR",
1028            "arrow long string longer than 12 bytes"
1029        ],
1030        "aRRow%",
1031        ilike,
1032        vec![true, false, true, false, true]
1033    );
1034
1035    test_utf8_scalar!(
1036        test_utf8_array_ilike_scalar_end,
1037        vec![
1038            "ArroW",
1039            "parrow",
1040            "ARRowS",
1041            "arr",
1042            "arrow long string longer than 12 bytes"
1043        ],
1044        "%arrow",
1045        ilike,
1046        vec![true, true, false, false, false]
1047    );
1048
1049    test_utf8_scalar!(
1050        test_utf8_array_ilike_scalar_equals,
1051        vec![
1052            "arrow",
1053            "parrow",
1054            "arrows",
1055            "arr",
1056            "arrow long string longer than 12 bytes"
1057        ],
1058        "Arrow",
1059        ilike,
1060        vec![true, false, false, false, false]
1061    );
1062
1063    // We only implement loose matching
1064    test_utf8_scalar!(
1065        #[cfg_attr(miri, ignore)] // Takes too long
1066        test_utf8_array_ilike_unicode,
1067        vec![
1068            "FFkoß",
1069            "FFkoSS",
1070            "FFkoss",
1071            "FFkoS",
1072            "FFkos",
1073            "ffkoSS",
1074            "ffkoß",
1075            "FFKoSS",
1076            "longer than 12 bytes FFKoSS"
1077        ],
1078        "FFkoSS",
1079        ilike,
1080        vec![false, true, true, false, false, false, false, true, false]
1081    );
1082
1083    test_utf8_scalar!(
1084        #[cfg_attr(miri, ignore)] // Takes too long
1085        test_utf8_array_ilike_unicode_starts,
1086        vec![
1087            "FFkoßsdlkdf",
1088            "FFkoSSsdlkdf",
1089            "FFkosssdlkdf",
1090            "FFkoS",
1091            "FFkos",
1092            "ffkoSS",
1093            "ffkoß",
1094            "FfkosSsdfd",
1095            "FFKoSS",
1096            "longer than 12 bytes FFKoSS",
1097        ],
1098        "FFkoSS%",
1099        ilike,
1100        vec![
1101            false, true, true, false, false, false, false, true, true, false
1102        ]
1103    );
1104
1105    test_utf8_scalar!(
1106        #[cfg_attr(miri, ignore)] // Takes too long
1107        test_utf8_array_ilike_unicode_ends,
1108        vec![
1109            "sdlkdfFFkoß",
1110            "sdlkdfFFkoSS",
1111            "sdlkdfFFkoss",
1112            "FFkoS",
1113            "FFkos",
1114            "ffkoSS",
1115            "ffkoß",
1116            "h😃klFfkosS",
1117            "FFKoSS",
1118            "longer than 12 bytes FFKoSS",
1119        ],
1120        "%FFkoSS",
1121        ilike,
1122        vec![
1123            false, true, true, false, false, false, false, true, true, true
1124        ]
1125    );
1126
1127    test_utf8_scalar!(
1128        #[cfg_attr(miri, ignore)] // Takes too long
1129        test_utf8_array_ilike_unicode_contains,
1130        vec![
1131            "sdlkdfFkoßsdfs",
1132            "sdlkdfFkoSSdggs",
1133            "sdlkdfFkosssdsd",
1134            "FkoS",
1135            "Fkos",
1136            "ffkoSS",
1137            "ffkoß",
1138            "😃sadlksffkosSsh😃klF",
1139            "😱slgffkosSsh😃klF",
1140            "FFKoSS",
1141            "longer than 12 bytes FFKoSS",
1142        ],
1143        "%FFkoSS%",
1144        ilike,
1145        vec![
1146            false, true, true, false, false, false, false, true, true, true, true
1147        ]
1148    );
1149
1150    // Replicates `test_utf8_array_ilike_unicode_contains` and
1151    // `test_utf8_array_ilike_unicode_contains_dyn` to
1152    // demonstrate that `SQL CONTAINS` works as expected.
1153    //
1154    // NOTE: 5 of the values were changed because the original used a case insensitive `ilike`.
1155    test_utf8_and_binary_scalar!(
1156        test_utf8_and_binary_array_contains_unicode_contains,
1157        vec![
1158            "sdlkdfFkoßsdfs",
1159            "sdlkdFFkoSSdggs", // Original was case insensitive "sdlkdfFkoSSdggs"
1160            "sdlkdFFkoSSsdsd", // Original was case insensitive "sdlkdfFkosssdsd"
1161            "FkoS",
1162            "Fkos",
1163            "ffkoSS",
1164            "ffkoß",
1165            "😃sadlksFFkoSSsh😃klF", // Original was case insensitive "😃sadlksffkosSsh😃klF"
1166            "😱slgFFkoSSsh😃klF",    // Original was case insensitive "😱slgffkosSsh😃klF"
1167            "FFkoSS",                // "FFKoSS"
1168            "longer than 12 bytes FFKoSS",
1169        ],
1170        "FFkoSS",
1171        contains,
1172        vec![
1173            false, true, true, false, false, false, false, true, true, true, false
1174        ]
1175    );
1176
1177    test_utf8_scalar!(
1178        #[cfg_attr(miri, ignore)] // Takes too long
1179        test_utf8_array_ilike_unicode_complex,
1180        vec![
1181            "sdlkdfFooßsdfs",
1182            "sdlkdfFooSSdggs",
1183            "sdlkdfFoosssdsd",
1184            "FooS",
1185            "Foos",
1186            "ffooSS",
1187            "ffooß",
1188            "😃sadlksffofsSsh😃klF",
1189            "😱slgffoesSsh😃klF",
1190            "FFKoSS",
1191            "longer than 12 bytes FFKoSS",
1192        ],
1193        "%FF__SS%",
1194        ilike,
1195        vec![
1196            false, true, true, false, false, false, false, true, true, true, true
1197        ]
1198    );
1199
1200    // 😈 is four bytes long.
1201    test_utf8_scalar!(
1202        test_uff8_array_like_multibyte,
1203        vec![
1204            "sdlkdfFooßsdfs",
1205            "sdlkdfFooSSdggs",
1206            "sdlkdfFoosssdsd",
1207            "FooS",
1208            "Foos",
1209            "ffooSS",
1210            "ffooß",
1211            "😃sadlksffofsSsh😈klF",
1212            "😱slgffoesSsh😈klF",
1213            "FFKoSS",
1214            "longer than 12 bytes FFKoSS",
1215        ],
1216        "%Ssh😈klF",
1217        like,
1218        vec![
1219            false, false, false, false, false, false, false, true, true, false, false
1220        ]
1221    );
1222
1223    test_utf8_scalar!(
1224        #[cfg_attr(miri, ignore)] // Takes too long
1225        test_utf8_array_ilike_scalar_one,
1226        vec![
1227            "arrow",
1228            "arrows",
1229            "parrow",
1230            "arr",
1231            "arrow long string longer than 12 bytes"
1232        ],
1233        "arrow_",
1234        ilike,
1235        vec![false, true, false, false, false]
1236    );
1237
1238    test_utf8!(
1239        #[cfg_attr(miri, ignore)] // Takes too long
1240        test_utf8_array_nilike,
1241        vec![
1242            "arrow",
1243            "arrow",
1244            "ARROW longer than 12 bytes string",
1245            "arrow",
1246            "ARROW",
1247            "ARROWS",
1248            "arROw"
1249        ],
1250        vec!["arrow", "ar%", "%ro%", "foo", "ar%r", "arrow_", "arrow_"],
1251        nilike,
1252        vec![false, false, false, true, true, false, true]
1253    );
1254
1255    test_utf8_scalar!(
1256        #[cfg_attr(miri, ignore)] // Takes too long
1257        nilike_utf8_scalar_escape_testing,
1258        vec![
1259            "varchar(255)",
1260            "int(255) longer than 12 bytes string",
1261            "varchar",
1262            "int"
1263        ],
1264        "%(%)%",
1265        nilike,
1266        vec![false, false, true, true]
1267    );
1268
1269    test_utf8_scalar!(
1270        test_utf8_array_nilike_scalar,
1271        vec![
1272            "arrow",
1273            "parquet",
1274            "datafusion",
1275            "flight",
1276            "arrow long string longer than 12 bytes"
1277        ],
1278        "%AR%",
1279        nilike,
1280        vec![false, false, true, true, false]
1281    );
1282
1283    test_utf8_scalar!(
1284        test_utf8_array_nilike_scalar_start,
1285        vec![
1286            "arrow",
1287            "parrow",
1288            "arrows",
1289            "ARR",
1290            "arrow long string longer than 12 bytes"
1291        ],
1292        "aRRow%",
1293        nilike,
1294        vec![false, true, false, true, false]
1295    );
1296
1297    test_utf8_scalar!(
1298        test_utf8_array_nilike_scalar_end,
1299        vec![
1300            "ArroW",
1301            "parrow",
1302            "ARRowS",
1303            "arr",
1304            "arrow long string longer than 12 bytes"
1305        ],
1306        "%arrow",
1307        nilike,
1308        vec![false, false, true, true, true]
1309    );
1310
1311    test_utf8_scalar!(
1312        test_utf8_array_nilike_scalar_equals,
1313        vec![
1314            "arRow",
1315            "parrow",
1316            "arrows",
1317            "arr",
1318            "arrow long string longer than 12 bytes"
1319        ],
1320        "Arrow",
1321        nilike,
1322        vec![false, true, true, true, true]
1323    );
1324
1325    test_utf8_scalar!(
1326        #[cfg_attr(miri, ignore)] // Takes too long
1327        test_utf8_array_nilike_scalar_one,
1328        vec![
1329            "arrow",
1330            "arrows",
1331            "parrow",
1332            "arr",
1333            "arrow long string longer than 12 bytes"
1334        ],
1335        "arrow_",
1336        nilike,
1337        vec![true, false, true, true, true]
1338    );
1339
1340    // Nullable, repeated values exercise dictionary remapping with a plain UTF8 scalar RHS.
1341    test_utf8_scalar!(
1342        test_utf8_scalar_nullable_like,
1343        vec![
1344            Some("Earth"),
1345            Some("Fire"),
1346            Some("Water"),
1347            Some("Air"),
1348            None,
1349            Some("Air"),
1350            Some("bbbbb\nAir")
1351        ],
1352        "Air",
1353        like,
1354        vec![
1355            Some(false),
1356            Some(false),
1357            Some(false),
1358            Some(true),
1359            None,
1360            Some(true),
1361            Some(false)
1362        ]
1363    );
1364
1365    test_utf8_scalar!(
1366        #[cfg_attr(miri, ignore)] // Takes too long
1367        test_utf8_scalar_nullable_nlike,
1368        vec![
1369            Some("Earth"),
1370            Some("Fire"),
1371            Some("Water"),
1372            Some("Air"),
1373            None,
1374            Some("Air"),
1375            Some("bbbbb\nAir")
1376        ],
1377        "%a%r%",
1378        nlike,
1379        vec![
1380            Some(false),
1381            Some(true),
1382            Some(false),
1383            Some(true),
1384            None,
1385            Some(true),
1386            Some(true)
1387        ]
1388    );
1389
1390    test_utf8_scalar!(
1391        test_utf8_scalar_nullable_ilike,
1392        vec![
1393            Some("Earth"),
1394            Some("Fire"),
1395            Some("Water"),
1396            Some("Air"),
1397            None,
1398            Some("Air"),
1399            Some("bbbbb\nAir")
1400        ],
1401        "%I%",
1402        ilike,
1403        vec![
1404            Some(false),
1405            Some(true),
1406            Some(false),
1407            Some(true),
1408            None,
1409            Some(true),
1410            Some(true)
1411        ]
1412    );
1413
1414    test_utf8_scalar!(
1415        test_utf8_scalar_nullable_nilike,
1416        vec![
1417            Some("Earth"),
1418            Some("Fire"),
1419            Some("Water"),
1420            Some("Air"),
1421            None,
1422            Some("Air"),
1423            Some("bbbbb\nAir")
1424        ],
1425        "%R",
1426        nilike,
1427        vec![
1428            Some(true),
1429            Some(true),
1430            Some(false),
1431            Some(false),
1432            None,
1433            Some(false),
1434            Some(false)
1435        ]
1436    );
1437
1438    #[test]
1439    #[cfg_attr(miri, ignore)] // Takes too long
1440    fn string_null_like_pattern() {
1441        // Different patterns have different execution code paths
1442        for pattern in &[
1443            "",           // can execute as equality check
1444            "_",          // can execute as length check
1445            "%",          // can execute as starts_with("") or non-null check
1446            "a%",         // can execute as starts_with("a")
1447            "%a",         // can execute as ends_with("")
1448            "a%b",        // can execute as starts_with("a") && ends_with("b")
1449            "%a%",        // can_execute as contains("a")
1450            "%a%b_c_d%e", // can_execute as regular expression
1451        ] {
1452            // These tests focus on the null handling, but are case-insensitive
1453            for like_f in [like, ilike, nlike, nilike] {
1454                let a = Scalar::new(StringArray::new_null(1));
1455                let b = StringArray::new_scalar(pattern);
1456                let r = like_f(&a, &b).unwrap();
1457                assert_eq!(r.len(), 1, "With pattern {pattern}");
1458                assert_eq!(r.null_count(), 1, "With pattern {pattern}");
1459                assert!(r.is_null(0), "With pattern {pattern}");
1460
1461                let a = Scalar::new(StringArray::new_null(1));
1462                let b = StringArray::from_iter_values([pattern]);
1463                let r = like_f(&a, &b).unwrap();
1464                assert_eq!(r.len(), 1, "With pattern {pattern}");
1465                assert_eq!(r.null_count(), 1, "With pattern {pattern}");
1466                assert!(r.is_null(0), "With pattern {pattern}");
1467
1468                let a = StringArray::new_null(1);
1469                let b = StringArray::from_iter_values([pattern]);
1470                let r = like_f(&a, &b).unwrap();
1471                assert_eq!(r.len(), 1, "With pattern {pattern}");
1472                assert_eq!(r.null_count(), 1, "With pattern {pattern}");
1473                assert!(r.is_null(0), "With pattern {pattern}");
1474
1475                let a = StringArray::new_null(1);
1476                let b = StringArray::new_scalar(pattern);
1477                let r = like_f(&a, &b).unwrap();
1478                assert_eq!(r.len(), 1, "With pattern {pattern}");
1479                assert_eq!(r.null_count(), 1, "With pattern {pattern}");
1480                assert!(r.is_null(0), "With pattern {pattern}");
1481            }
1482        }
1483    }
1484
1485    #[test]
1486    #[cfg_attr(miri, ignore)] // Takes too long
1487    fn string_view_null_like_pattern() {
1488        // Different patterns have different execution code paths
1489        for pattern in &[
1490            "",           // can execute as equality check
1491            "_",          // can execute as length check
1492            "%",          // can execute as starts_with("") or non-null check
1493            "a%",         // can execute as starts_with("a")
1494            "%a",         // can execute as ends_with("")
1495            "a%b",        // can execute as starts_with("a") && ends_with("b")
1496            "%a%",        // can_execute as contains("a")
1497            "%a%b_c_d%e", // can_execute as regular expression
1498        ] {
1499            // These tests focus on the null handling, but are case-insensitive
1500            for like_f in [like, ilike, nlike, nilike] {
1501                let a = Scalar::new(StringViewArray::new_null(1));
1502                let b = StringViewArray::new_scalar(pattern);
1503                let r = like_f(&a, &b).unwrap();
1504                assert_eq!(r.len(), 1, "With pattern {pattern}");
1505                assert_eq!(r.null_count(), 1, "With pattern {pattern}");
1506                assert!(r.is_null(0), "With pattern {pattern}");
1507
1508                let a = Scalar::new(StringViewArray::new_null(1));
1509                let b = StringViewArray::from_iter_values([pattern]);
1510                let r = like_f(&a, &b).unwrap();
1511                assert_eq!(r.len(), 1, "With pattern {pattern}");
1512                assert_eq!(r.null_count(), 1, "With pattern {pattern}");
1513                assert!(r.is_null(0), "With pattern {pattern}");
1514
1515                let a = StringViewArray::new_null(1);
1516                let b = StringViewArray::from_iter_values([pattern]);
1517                let r = like_f(&a, &b).unwrap();
1518                assert_eq!(r.len(), 1, "With pattern {pattern}");
1519                assert_eq!(r.null_count(), 1, "With pattern {pattern}");
1520                assert!(r.is_null(0), "With pattern {pattern}");
1521
1522                let a = StringViewArray::new_null(1);
1523                let b = StringViewArray::new_scalar(pattern);
1524                let r = like_f(&a, &b).unwrap();
1525                assert_eq!(r.len(), 1, "With pattern {pattern}");
1526                assert_eq!(r.null_count(), 1, "With pattern {pattern}");
1527                assert!(r.is_null(0), "With pattern {pattern}");
1528            }
1529        }
1530    }
1531
1532    #[test]
1533    fn string_like_scalar_null() {
1534        for like_f in [like, ilike, nlike, nilike] {
1535            let a = StringArray::new_scalar("a");
1536            let b = Scalar::new(StringArray::new_null(1));
1537            let r = like_f(&a, &b).unwrap();
1538            assert_eq!(r.len(), 1);
1539            assert_eq!(r.null_count(), 1);
1540            assert!(r.is_null(0));
1541
1542            let a = StringArray::from_iter_values(["a"]);
1543            let b = Scalar::new(StringArray::new_null(1));
1544            let r = like_f(&a, &b).unwrap();
1545            assert_eq!(r.len(), 1);
1546            assert_eq!(r.null_count(), 1);
1547            assert!(r.is_null(0));
1548
1549            let a = StringArray::from_iter_values(["a"]);
1550            let b = StringArray::new_null(1);
1551            let r = like_f(&a, &b).unwrap();
1552            assert_eq!(r.len(), 1);
1553            assert_eq!(r.null_count(), 1);
1554            assert!(r.is_null(0));
1555
1556            let a = StringArray::new_scalar("a");
1557            let b = StringArray::new_null(1);
1558            let r = like_f(&a, &b).unwrap();
1559            assert_eq!(r.len(), 1);
1560            assert_eq!(r.null_count(), 1);
1561            assert!(r.is_null(0));
1562        }
1563    }
1564
1565    #[test]
1566    fn string_view_like_scalar_null() {
1567        for like_f in [like, ilike, nlike, nilike] {
1568            let a = StringViewArray::new_scalar("a");
1569            let b = Scalar::new(StringViewArray::new_null(1));
1570            let r = like_f(&a, &b).unwrap();
1571            assert_eq!(r.len(), 1);
1572            assert_eq!(r.null_count(), 1);
1573            assert!(r.is_null(0));
1574
1575            let a = StringViewArray::from_iter_values(["a"]);
1576            let b = Scalar::new(StringViewArray::new_null(1));
1577            let r = like_f(&a, &b).unwrap();
1578            assert_eq!(r.len(), 1);
1579            assert_eq!(r.null_count(), 1);
1580            assert!(r.is_null(0));
1581
1582            let a = StringViewArray::from_iter_values(["a"]);
1583            let b = StringViewArray::new_null(1);
1584            let r = like_f(&a, &b).unwrap();
1585            assert_eq!(r.len(), 1);
1586            assert_eq!(r.null_count(), 1);
1587            assert!(r.is_null(0));
1588
1589            let a = StringViewArray::new_scalar("a");
1590            let b = StringViewArray::new_null(1);
1591            let r = like_f(&a, &b).unwrap();
1592            assert_eq!(r.len(), 1);
1593            assert_eq!(r.null_count(), 1);
1594            assert!(r.is_null(0));
1595        }
1596    }
1597
1598    #[test]
1599    #[cfg_attr(miri, ignore)] // Takes too long
1600    fn like_escape() {
1601        // (value, pattern, expected)
1602        let test_cases = vec![
1603            // Empty pattern
1604            (r"", r"", true),
1605            (r"\", r"", false),
1606            // Sole (dangling) escape (some engines consider this invalid pattern)
1607            (r"", r"\", false),
1608            (r"\", r"\", true),
1609            (r"\\", r"\", false),
1610            (r"a", r"\", false),
1611            (r"\a", r"\", false),
1612            (r"\\a", r"\", false),
1613            // Sole escape
1614            (r"", r"\\", false),
1615            (r"\", r"\\", true),
1616            (r"\\", r"\\", false),
1617            (r"a", r"\\", false),
1618            (r"\a", r"\\", false),
1619            (r"\\a", r"\\", false),
1620            // Sole escape and dangling escape
1621            (r"", r"\\\", false),
1622            (r"\", r"\\\", false),
1623            (r"\\", r"\\\", true),
1624            (r"\\\", r"\\\", false),
1625            (r"\\\\", r"\\\", false),
1626            (r"a", r"\\\", false),
1627            (r"\a", r"\\\", false),
1628            (r"\\a", r"\\\", false),
1629            // Sole two escapes
1630            (r"", r"\\\\", false),
1631            (r"\", r"\\\\", false),
1632            (r"\\", r"\\\\", true),
1633            (r"\\\", r"\\\\", false),
1634            (r"\\\\", r"\\\\", false),
1635            (r"\\\\\", r"\\\\", false),
1636            (r"a", r"\\\\", false),
1637            (r"\a", r"\\\\", false),
1638            (r"\\a", r"\\\\", false),
1639            // Escaped non-wildcard
1640            (r"", r"\a", false),
1641            (r"\", r"\a", false),
1642            (r"\\", r"\a", false),
1643            (r"a", r"\a", true),
1644            (r"\a", r"\a", false),
1645            (r"\\a", r"\a", false),
1646            // Escaped _ wildcard
1647            (r"", r"\_", false),
1648            (r"\", r"\_", false),
1649            (r"\\", r"\_", false),
1650            (r"a", r"\_", false),
1651            (r"_", r"\_", true),
1652            (r"%", r"\_", false),
1653            (r"\a", r"\_", false),
1654            (r"\\a", r"\_", false),
1655            (r"\_", r"\_", false),
1656            (r"\\_", r"\_", false),
1657            // Escaped % wildcard
1658            (r"", r"\%", false),
1659            (r"\", r"\%", false),
1660            (r"\\", r"\%", false),
1661            (r"a", r"\%", false),
1662            (r"_", r"\%", false),
1663            (r"%", r"\%", true),
1664            (r"\a", r"\%", false),
1665            (r"\\a", r"\%", false),
1666            (r"\%", r"\%", false),
1667            (r"\\%", r"\%", false),
1668            // Escape and non-wildcard
1669            (r"", r"\\a", false),
1670            (r"\", r"\\a", false),
1671            (r"\\", r"\\a", false),
1672            (r"a", r"\\a", false),
1673            (r"\a", r"\\a", true),
1674            (r"\\a", r"\\a", false),
1675            (r"\\\a", r"\\a", false),
1676            // Escape and _ wildcard
1677            (r"", r"\\_", false),
1678            (r"\", r"\\_", false),
1679            (r"\\", r"\\_", true),
1680            (r"a", r"\\_", false),
1681            (r"_", r"\\_", false),
1682            (r"%", r"\\_", false),
1683            (r"\a", r"\\_", true),
1684            (r"\\a", r"\\_", false),
1685            (r"\_", r"\\_", true),
1686            (r"\\_", r"\\_", false),
1687            (r"\\\_", r"\\_", false),
1688            // Escape and % wildcard
1689            (r"", r"\\%", false),
1690            (r"\", r"\\%", true),
1691            (r"\\", r"\\%", true),
1692            (r"a", r"\\%", false),
1693            (r"ab", r"\\%", false),
1694            (r"a%", r"\\%", false),
1695            (r"_", r"\\%", false),
1696            (r"%", r"\\%", false),
1697            (r"\a", r"\\%", true),
1698            (r"\\a", r"\\%", true),
1699            (r"\%", r"\\%", true),
1700            (r"\\%", r"\\%", true),
1701            (r"\\\%", r"\\%", true),
1702            // %... pattern with dangling wildcard
1703            (r"\", r"%\", true),
1704            (r"\\", r"%\", true),
1705            (r"%\", r"%\", true),
1706            (r"%\\", r"%\", true),
1707            (r"abc\", r"%\", true),
1708            (r"abc", r"%\", false),
1709            // %... pattern with wildcard
1710            (r"\", r"%\\", true),
1711            (r"\\", r"%\\", true),
1712            (r"%\\", r"%\\", true),
1713            (r"%\\\", r"%\\", true),
1714            (r"abc\", r"%\\", true),
1715            (r"abc", r"%\\", false),
1716            // %... pattern including escaped non-wildcard
1717            (r"ac", r"%a\c", true),
1718            (r"xyzac", r"%a\c", true),
1719            (r"abc", r"%a\c", false),
1720            (r"a\c", r"%a\c", false),
1721            (r"%a\c", r"%a\c", false),
1722            // %... pattern including escape
1723            (r"\", r"%a\\c", false),
1724            (r"\\", r"%a\\c", false),
1725            (r"ac", r"%a\\c", false),
1726            (r"a\c", r"%a\\c", true),
1727            (r"a\\c", r"%a\\c", false),
1728            (r"abc", r"%a\\c", false),
1729            (r"xyza\c", r"%a\\c", true),
1730            (r"xyza\\c", r"%a\\c", false),
1731            (r"%a\\c", r"%a\\c", false),
1732            // ...% pattern with wildcard
1733            (r"\", r"\\%", true),
1734            (r"\\", r"\\%", true),
1735            (r"\\%", r"\\%", true),
1736            (r"\\\%", r"\\%", true),
1737            (r"\abc", r"\\%", true),
1738            (r"a", r"\\%", false),
1739            (r"abc", r"\\%", false),
1740            // ...% pattern including escaped non-wildcard
1741            (r"ac", r"a\c%", true),
1742            (r"acxyz", r"a\c%", true),
1743            (r"abc", r"a\c%", false),
1744            (r"a\c", r"a\c%", false),
1745            (r"a\c%", r"a\c%", false),
1746            (r"a\\c%", r"a\c%", false),
1747            // ...% pattern including escape
1748            (r"ac", r"a\\c%", false),
1749            (r"a\c", r"a\\c%", true),
1750            (r"a\cxyz", r"a\\c%", true),
1751            (r"a\\c", r"a\\c%", false),
1752            (r"a\\cxyz", r"a\\c%", false),
1753            (r"abc", r"a\\c%", false),
1754            (r"abcxyz", r"a\\c%", false),
1755            (r"a\\c%", r"a\\c%", false),
1756            // %...% pattern including escaped non-wildcard
1757            (r"ac", r"%a\c%", true),
1758            (r"xyzacxyz", r"%a\c%", true),
1759            (r"abc", r"%a\c%", false),
1760            (r"a\c", r"%a\c%", false),
1761            (r"xyza\cxyz", r"%a\c%", false),
1762            (r"%a\c%", r"%a\c%", false),
1763            (r"%a\\c%", r"%a\c%", false),
1764            // %...% pattern including escape
1765            (r"ac", r"%a\\c%", false),
1766            (r"a\c", r"%a\\c%", true),
1767            (r"xyza\cxyz", r"%a\\c%", true),
1768            (r"a\\c", r"%a\\c%", false),
1769            (r"xyza\\cxyz", r"%a\\c%", false),
1770            (r"abc", r"%a\\c%", false),
1771            (r"xyzabcxyz", r"%a\\c%", false),
1772            (r"%a\\c%", r"%a\\c%", false),
1773            // Odd (7) backslashes and % wildcard
1774            (r"\\%", r"\\\\\\\%", false),
1775            (r"\\\", r"\\\\\\\%", false),
1776            (r"\\\%", r"\\\\\\\%", true),
1777            (r"\\\\", r"\\\\\\\%", false),
1778            (r"\\\\%", r"\\\\\\\%", false),
1779            (r"\\\\\\\%", r"\\\\\\\%", false),
1780            // Odd (7) backslashes and _ wildcard
1781            (r"\\\", r"\\\\\\\_", false),
1782            (r"\\\\", r"\\\\\\\_", false),
1783            (r"\\\_", r"\\\\\\\_", true),
1784            (r"\\\\", r"\\\\\\\_", false),
1785            (r"\\\a", r"\\\\\\\_", false),
1786            (r"\\\\_", r"\\\\\\\_", false),
1787            (r"\\\\\\\_", r"\\\\\\\_", false),
1788            // Even (8) backslashes and % wildcard
1789            (r"\\\", r"\\\\\\\\%", false),
1790            (r"\\\\", r"\\\\\\\\%", true),
1791            (r"\\\\\", r"\\\\\\\\%", true),
1792            (r"\\\\xyz", r"\\\\\\\\%", true),
1793            (r"\\\\\\\\%", r"\\\\\\\\%", true),
1794            // Even (8) backslashes and _ wildcard
1795            (r"\\\", r"\\\\\\\\_", false),
1796            (r"\\\\", r"\\\\\\\\_", false),
1797            (r"\\\\\", r"\\\\\\\\_", true),
1798            (r"\\\\a", r"\\\\\\\\_", true),
1799            (r"\\\\\a", r"\\\\\\\\_", false),
1800            (r"\\\\ab", r"\\\\\\\\_", false),
1801            (r"\\\\\\\\_", r"\\\\\\\\_", false),
1802        ];
1803
1804        for (value, pattern, expected) in test_cases {
1805            let unexpected = BooleanArray::from(vec![!expected]);
1806            let expected = BooleanArray::from(vec![expected]);
1807
1808            for string_type in [DataType::Utf8, DataType::LargeUtf8, DataType::Utf8View] {
1809                for ((value_datum, value_type), (pattern_datum, pattern_type)) in zip(
1810                    make_datums(value, &string_type),
1811                    make_datums(pattern, &string_type),
1812                ) {
1813                    let value_datum = value_datum.as_ref();
1814                    let pattern_datum = pattern_datum.as_ref();
1815                    assert_eq!(
1816                        like(value_datum, pattern_datum).unwrap(),
1817                        expected,
1818                        "{value_type:?} «{value}» like {pattern_type:?} «{pattern}»"
1819                    );
1820                    assert_eq!(
1821                        ilike(value_datum, pattern_datum).unwrap(),
1822                        expected,
1823                        "{value_type:?} «{value}» ilike {pattern_type:?} «{pattern}»"
1824                    );
1825                    assert_eq!(
1826                        nlike(value_datum, pattern_datum).unwrap(),
1827                        unexpected,
1828                        "{value_type:?} «{value}» nlike {pattern_type:?} «{pattern}»"
1829                    );
1830                    assert_eq!(
1831                        nilike(value_datum, pattern_datum).unwrap(),
1832                        unexpected,
1833                        "{value_type:?} «{value}» nilike {pattern_type:?} «{pattern}»"
1834                    );
1835                }
1836            }
1837        }
1838    }
1839
1840    #[test]
1841    #[cfg_attr(miri, ignore)] // Takes too long
1842    fn like_escape_many() {
1843        // (value, pattern, expected)
1844        let test_cases = vec![
1845            (r"", r"", true),
1846            (r"\", r"", false),
1847            (r"\\", r"", false),
1848            (r"\\\", r"", false),
1849            (r"\\\\", r"", false),
1850            (r"a", r"", false),
1851            (r"\a", r"", false),
1852            (r"\\a", r"", false),
1853            (r"%", r"", false),
1854            (r"\%", r"", false),
1855            (r"\\%", r"", false),
1856            (r"%%", r"", false),
1857            (r"\%%", r"", false),
1858            (r"\\%%", r"", false),
1859            (r"_", r"", false),
1860            (r"\_", r"", false),
1861            (r"\\_", r"", false),
1862            (r"__", r"", false),
1863            (r"\__", r"", false),
1864            (r"\\__", r"", false),
1865            (r"abc", r"", false),
1866            (r"a_c", r"", false),
1867            (r"a\bc", r"", false),
1868            (r"a\_c", r"", false),
1869            (r"%abc", r"", false),
1870            (r"\%abc", r"", false),
1871            (r"a\\_c%", r"", false),
1872            (r"", r"\", false),
1873            (r"\", r"\", true),
1874            (r"\\", r"\", false),
1875            (r"\\\", r"\", false),
1876            (r"\\\\", r"\", false),
1877            (r"a", r"\", false),
1878            (r"\a", r"\", false),
1879            (r"\\a", r"\", false),
1880            (r"%", r"\", false),
1881            (r"\%", r"\", false),
1882            (r"\\%", r"\", false),
1883            (r"%%", r"\", false),
1884            (r"\%%", r"\", false),
1885            (r"\\%%", r"\", false),
1886            (r"_", r"\", false),
1887            (r"\_", r"\", false),
1888            (r"\\_", r"\", false),
1889            (r"__", r"\", false),
1890            (r"\__", r"\", false),
1891            (r"\\__", r"\", false),
1892            (r"abc", r"\", false),
1893            (r"a_c", r"\", false),
1894            (r"a\bc", r"\", false),
1895            (r"a\_c", r"\", false),
1896            (r"%abc", r"\", false),
1897            (r"\%abc", r"\", false),
1898            (r"a\\_c%", r"\", false),
1899            (r"", r"\\", false),
1900            (r"\", r"\\", true),
1901            (r"\\", r"\\", false),
1902            (r"\\\", r"\\", false),
1903            (r"\\\\", r"\\", false),
1904            (r"a", r"\\", false),
1905            (r"\a", r"\\", false),
1906            (r"\\a", r"\\", false),
1907            (r"%", r"\\", false),
1908            (r"\%", r"\\", false),
1909            (r"\\%", r"\\", false),
1910            (r"%%", r"\\", false),
1911            (r"\%%", r"\\", false),
1912            (r"\\%%", r"\\", false),
1913            (r"_", r"\\", false),
1914            (r"\_", r"\\", false),
1915            (r"\\_", r"\\", false),
1916            (r"__", r"\\", false),
1917            (r"\__", r"\\", false),
1918            (r"\\__", r"\\", false),
1919            (r"abc", r"\\", false),
1920            (r"a_c", r"\\", false),
1921            (r"a\bc", r"\\", false),
1922            (r"a\_c", r"\\", false),
1923            (r"%abc", r"\\", false),
1924            (r"\%abc", r"\\", false),
1925            (r"a\\_c%", r"\\", false),
1926            (r"", r"\\\", false),
1927            (r"\", r"\\\", false),
1928            (r"\\", r"\\\", true),
1929            (r"\\\", r"\\\", false),
1930            (r"\\\\", r"\\\", false),
1931            (r"a", r"\\\", false),
1932            (r"\a", r"\\\", false),
1933            (r"\\a", r"\\\", false),
1934            (r"%", r"\\\", false),
1935            (r"\%", r"\\\", false),
1936            (r"\\%", r"\\\", false),
1937            (r"%%", r"\\\", false),
1938            (r"\%%", r"\\\", false),
1939            (r"\\%%", r"\\\", false),
1940            (r"_", r"\\\", false),
1941            (r"\_", r"\\\", false),
1942            (r"\\_", r"\\\", false),
1943            (r"__", r"\\\", false),
1944            (r"\__", r"\\\", false),
1945            (r"\\__", r"\\\", false),
1946            (r"abc", r"\\\", false),
1947            (r"a_c", r"\\\", false),
1948            (r"a\bc", r"\\\", false),
1949            (r"a\_c", r"\\\", false),
1950            (r"%abc", r"\\\", false),
1951            (r"\%abc", r"\\\", false),
1952            (r"a\\_c%", r"\\\", false),
1953            (r"", r"\\\\", false),
1954            (r"\", r"\\\\", false),
1955            (r"\\", r"\\\\", true),
1956            (r"\\\", r"\\\\", false),
1957            (r"\\\\", r"\\\\", false),
1958            (r"a", r"\\\\", false),
1959            (r"\a", r"\\\\", false),
1960            (r"\\a", r"\\\\", false),
1961            (r"%", r"\\\\", false),
1962            (r"\%", r"\\\\", false),
1963            (r"\\%", r"\\\\", false),
1964            (r"%%", r"\\\\", false),
1965            (r"\%%", r"\\\\", false),
1966            (r"\\%%", r"\\\\", false),
1967            (r"_", r"\\\\", false),
1968            (r"\_", r"\\\\", false),
1969            (r"\\_", r"\\\\", false),
1970            (r"__", r"\\\\", false),
1971            (r"\__", r"\\\\", false),
1972            (r"\\__", r"\\\\", false),
1973            (r"abc", r"\\\\", false),
1974            (r"a_c", r"\\\\", false),
1975            (r"a\bc", r"\\\\", false),
1976            (r"a\_c", r"\\\\", false),
1977            (r"%abc", r"\\\\", false),
1978            (r"\%abc", r"\\\\", false),
1979            (r"a\\_c%", r"\\\\", false),
1980            (r"", r"a", false),
1981            (r"\", r"a", false),
1982            (r"\\", r"a", false),
1983            (r"\\\", r"a", false),
1984            (r"\\\\", r"a", false),
1985            (r"a", r"a", true),
1986            (r"\a", r"a", false),
1987            (r"\\a", r"a", false),
1988            (r"%", r"a", false),
1989            (r"\%", r"a", false),
1990            (r"\\%", r"a", false),
1991            (r"%%", r"a", false),
1992            (r"\%%", r"a", false),
1993            (r"\\%%", r"a", false),
1994            (r"_", r"a", false),
1995            (r"\_", r"a", false),
1996            (r"\\_", r"a", false),
1997            (r"__", r"a", false),
1998            (r"\__", r"a", false),
1999            (r"\\__", r"a", false),
2000            (r"abc", r"a", false),
2001            (r"a_c", r"a", false),
2002            (r"a\bc", r"a", false),
2003            (r"a\_c", r"a", false),
2004            (r"%abc", r"a", false),
2005            (r"\%abc", r"a", false),
2006            (r"a\\_c%", r"a", false),
2007            (r"", r"\a", false),
2008            (r"\", r"\a", false),
2009            (r"\\", r"\a", false),
2010            (r"\\\", r"\a", false),
2011            (r"\\\\", r"\a", false),
2012            (r"a", r"\a", true),
2013            (r"\a", r"\a", false),
2014            (r"\\a", r"\a", false),
2015            (r"%", r"\a", false),
2016            (r"\%", r"\a", false),
2017            (r"\\%", r"\a", false),
2018            (r"%%", r"\a", false),
2019            (r"\%%", r"\a", false),
2020            (r"\\%%", r"\a", false),
2021            (r"_", r"\a", false),
2022            (r"\_", r"\a", false),
2023            (r"\\_", r"\a", false),
2024            (r"__", r"\a", false),
2025            (r"\__", r"\a", false),
2026            (r"\\__", r"\a", false),
2027            (r"abc", r"\a", false),
2028            (r"a_c", r"\a", false),
2029            (r"a\bc", r"\a", false),
2030            (r"a\_c", r"\a", false),
2031            (r"%abc", r"\a", false),
2032            (r"\%abc", r"\a", false),
2033            (r"a\\_c%", r"\a", false),
2034            (r"", r"\\a", false),
2035            (r"\", r"\\a", false),
2036            (r"\\", r"\\a", false),
2037            (r"\\\", r"\\a", false),
2038            (r"\\\\", r"\\a", false),
2039            (r"a", r"\\a", false),
2040            (r"\a", r"\\a", true),
2041            (r"\\a", r"\\a", false),
2042            (r"%", r"\\a", false),
2043            (r"\%", r"\\a", false),
2044            (r"\\%", r"\\a", false),
2045            (r"%%", r"\\a", false),
2046            (r"\%%", r"\\a", false),
2047            (r"\\%%", r"\\a", false),
2048            (r"_", r"\\a", false),
2049            (r"\_", r"\\a", false),
2050            (r"\\_", r"\\a", false),
2051            (r"__", r"\\a", false),
2052            (r"\__", r"\\a", false),
2053            (r"\\__", r"\\a", false),
2054            (r"abc", r"\\a", false),
2055            (r"a_c", r"\\a", false),
2056            (r"a\bc", r"\\a", false),
2057            (r"a\_c", r"\\a", false),
2058            (r"%abc", r"\\a", false),
2059            (r"\%abc", r"\\a", false),
2060            (r"a\\_c%", r"\\a", false),
2061            (r"", r"%", true),
2062            (r"\", r"%", true),
2063            (r"\\", r"%", true),
2064            (r"\\\", r"%", true),
2065            (r"\\\\", r"%", true),
2066            (r"a", r"%", true),
2067            (r"\a", r"%", true),
2068            (r"\\a", r"%", true),
2069            (r"%", r"%", true),
2070            (r"\%", r"%", true),
2071            (r"\\%", r"%", true),
2072            (r"%%", r"%", true),
2073            (r"\%%", r"%", true),
2074            (r"\\%%", r"%", true),
2075            (r"_", r"%", true),
2076            (r"\_", r"%", true),
2077            (r"\\_", r"%", true),
2078            (r"__", r"%", true),
2079            (r"\__", r"%", true),
2080            (r"\\__", r"%", true),
2081            (r"abc", r"%", true),
2082            (r"a_c", r"%", true),
2083            (r"a\bc", r"%", true),
2084            (r"a\_c", r"%", true),
2085            (r"%abc", r"%", true),
2086            (r"\%abc", r"%", true),
2087            (r"a\\_c%", r"%", true),
2088            (r"", r"\%", false),
2089            (r"\", r"\%", false),
2090            (r"\\", r"\%", false),
2091            (r"\\\", r"\%", false),
2092            (r"\\\\", r"\%", false),
2093            (r"a", r"\%", false),
2094            (r"\a", r"\%", false),
2095            (r"\\a", r"\%", false),
2096            (r"%", r"\%", true),
2097            (r"\%", r"\%", false),
2098            (r"\\%", r"\%", false),
2099            (r"%%", r"\%", false),
2100            (r"\%%", r"\%", false),
2101            (r"\\%%", r"\%", false),
2102            (r"_", r"\%", false),
2103            (r"\_", r"\%", false),
2104            (r"\\_", r"\%", false),
2105            (r"__", r"\%", false),
2106            (r"\__", r"\%", false),
2107            (r"\\__", r"\%", false),
2108            (r"abc", r"\%", false),
2109            (r"a_c", r"\%", false),
2110            (r"a\bc", r"\%", false),
2111            (r"a\_c", r"\%", false),
2112            (r"%abc", r"\%", false),
2113            (r"\%abc", r"\%", false),
2114            (r"a\\_c%", r"\%", false),
2115            (r"", r"\\%", false),
2116            (r"\", r"\\%", true),
2117            (r"\\", r"\\%", true),
2118            (r"\\\", r"\\%", true),
2119            (r"\\\\", r"\\%", true),
2120            (r"a", r"\\%", false),
2121            (r"\a", r"\\%", true),
2122            (r"\\a", r"\\%", true),
2123            (r"%", r"\\%", false),
2124            (r"\%", r"\\%", true),
2125            (r"\\%", r"\\%", true),
2126            (r"%%", r"\\%", false),
2127            (r"\%%", r"\\%", true),
2128            (r"\\%%", r"\\%", true),
2129            (r"_", r"\\%", false),
2130            (r"\_", r"\\%", true),
2131            (r"\\_", r"\\%", true),
2132            (r"__", r"\\%", false),
2133            (r"\__", r"\\%", true),
2134            (r"\\__", r"\\%", true),
2135            (r"abc", r"\\%", false),
2136            (r"a_c", r"\\%", false),
2137            (r"a\bc", r"\\%", false),
2138            (r"a\_c", r"\\%", false),
2139            (r"%abc", r"\\%", false),
2140            (r"\%abc", r"\\%", true),
2141            (r"a\\_c%", r"\\%", false),
2142            (r"", r"%%", true),
2143            (r"\", r"%%", true),
2144            (r"\\", r"%%", true),
2145            (r"\\\", r"%%", true),
2146            (r"\\\\", r"%%", true),
2147            (r"a", r"%%", true),
2148            (r"\a", r"%%", true),
2149            (r"\\a", r"%%", true),
2150            (r"%", r"%%", true),
2151            (r"\%", r"%%", true),
2152            (r"\\%", r"%%", true),
2153            (r"%%", r"%%", true),
2154            (r"\%%", r"%%", true),
2155            (r"\\%%", r"%%", true),
2156            (r"_", r"%%", true),
2157            (r"\_", r"%%", true),
2158            (r"\\_", r"%%", true),
2159            (r"__", r"%%", true),
2160            (r"\__", r"%%", true),
2161            (r"\\__", r"%%", true),
2162            (r"abc", r"%%", true),
2163            (r"a_c", r"%%", true),
2164            (r"a\bc", r"%%", true),
2165            (r"a\_c", r"%%", true),
2166            (r"%abc", r"%%", true),
2167            (r"\%abc", r"%%", true),
2168            (r"a\\_c%", r"%%", true),
2169            (r"", r"\%%", false),
2170            (r"\", r"\%%", false),
2171            (r"\\", r"\%%", false),
2172            (r"\\\", r"\%%", false),
2173            (r"\\\\", r"\%%", false),
2174            (r"a", r"\%%", false),
2175            (r"\a", r"\%%", false),
2176            (r"\\a", r"\%%", false),
2177            (r"%", r"\%%", true),
2178            (r"\%", r"\%%", false),
2179            (r"\\%", r"\%%", false),
2180            (r"%%", r"\%%", true),
2181            (r"\%%", r"\%%", false),
2182            (r"\\%%", r"\%%", false),
2183            (r"_", r"\%%", false),
2184            (r"\_", r"\%%", false),
2185            (r"\\_", r"\%%", false),
2186            (r"__", r"\%%", false),
2187            (r"\__", r"\%%", false),
2188            (r"\\__", r"\%%", false),
2189            (r"abc", r"\%%", false),
2190            (r"a_c", r"\%%", false),
2191            (r"a\bc", r"\%%", false),
2192            (r"a\_c", r"\%%", false),
2193            (r"%abc", r"\%%", true),
2194            (r"\%abc", r"\%%", false),
2195            (r"a\\_c%", r"\%%", false),
2196            (r"", r"\\%%", false),
2197            (r"\", r"\\%%", true),
2198            (r"\\", r"\\%%", true),
2199            (r"\\\", r"\\%%", true),
2200            (r"\\\\", r"\\%%", true),
2201            (r"a", r"\\%%", false),
2202            (r"\a", r"\\%%", true),
2203            (r"\\a", r"\\%%", true),
2204            (r"%", r"\\%%", false),
2205            (r"\%", r"\\%%", true),
2206            (r"\\%", r"\\%%", true),
2207            (r"%%", r"\\%%", false),
2208            (r"\%%", r"\\%%", true),
2209            (r"\\%%", r"\\%%", true),
2210            (r"_", r"\\%%", false),
2211            (r"\_", r"\\%%", true),
2212            (r"\\_", r"\\%%", true),
2213            (r"__", r"\\%%", false),
2214            (r"\__", r"\\%%", true),
2215            (r"\\__", r"\\%%", true),
2216            (r"abc", r"\\%%", false),
2217            (r"a_c", r"\\%%", false),
2218            (r"a\bc", r"\\%%", false),
2219            (r"a\_c", r"\\%%", false),
2220            (r"%abc", r"\\%%", false),
2221            (r"\%abc", r"\\%%", true),
2222            (r"a\\_c%", r"\\%%", false),
2223            (r"", r"_", false),
2224            (r"\", r"_", true),
2225            (r"\\", r"_", false),
2226            (r"\\\", r"_", false),
2227            (r"\\\\", r"_", false),
2228            (r"a", r"_", true),
2229            (r"\a", r"_", false),
2230            (r"\\a", r"_", false),
2231            (r"%", r"_", true),
2232            (r"\%", r"_", false),
2233            (r"\\%", r"_", false),
2234            (r"%%", r"_", false),
2235            (r"\%%", r"_", false),
2236            (r"\\%%", r"_", false),
2237            (r"_", r"_", true),
2238            (r"\_", r"_", false),
2239            (r"\\_", r"_", false),
2240            (r"__", r"_", false),
2241            (r"\__", r"_", false),
2242            (r"\\__", r"_", false),
2243            (r"abc", r"_", false),
2244            (r"a_c", r"_", false),
2245            (r"a\bc", r"_", false),
2246            (r"a\_c", r"_", false),
2247            (r"%abc", r"_", false),
2248            (r"\%abc", r"_", false),
2249            (r"a\\_c%", r"_", false),
2250            (r"", r"\_", false),
2251            (r"\", r"\_", false),
2252            (r"\\", r"\_", false),
2253            (r"\\\", r"\_", false),
2254            (r"\\\\", r"\_", false),
2255            (r"a", r"\_", false),
2256            (r"\a", r"\_", false),
2257            (r"\\a", r"\_", false),
2258            (r"%", r"\_", false),
2259            (r"\%", r"\_", false),
2260            (r"\\%", r"\_", false),
2261            (r"%%", r"\_", false),
2262            (r"\%%", r"\_", false),
2263            (r"\\%%", r"\_", false),
2264            (r"_", r"\_", true),
2265            (r"\_", r"\_", false),
2266            (r"\\_", r"\_", false),
2267            (r"__", r"\_", false),
2268            (r"\__", r"\_", false),
2269            (r"\\__", r"\_", false),
2270            (r"abc", r"\_", false),
2271            (r"a_c", r"\_", false),
2272            (r"a\bc", r"\_", false),
2273            (r"a\_c", r"\_", false),
2274            (r"%abc", r"\_", false),
2275            (r"\%abc", r"\_", false),
2276            (r"a\\_c%", r"\_", false),
2277            (r"", r"\\_", false),
2278            (r"\", r"\\_", false),
2279            (r"\\", r"\\_", true),
2280            (r"\\\", r"\\_", false),
2281            (r"\\\\", r"\\_", false),
2282            (r"a", r"\\_", false),
2283            (r"\a", r"\\_", true),
2284            (r"\\a", r"\\_", false),
2285            (r"%", r"\\_", false),
2286            (r"\%", r"\\_", true),
2287            (r"\\%", r"\\_", false),
2288            (r"%%", r"\\_", false),
2289            (r"\%%", r"\\_", false),
2290            (r"\\%%", r"\\_", false),
2291            (r"_", r"\\_", false),
2292            (r"\_", r"\\_", true),
2293            (r"\\_", r"\\_", false),
2294            (r"__", r"\\_", false),
2295            (r"\__", r"\\_", false),
2296            (r"\\__", r"\\_", false),
2297            (r"abc", r"\\_", false),
2298            (r"a_c", r"\\_", false),
2299            (r"a\bc", r"\\_", false),
2300            (r"a\_c", r"\\_", false),
2301            (r"%abc", r"\\_", false),
2302            (r"\%abc", r"\\_", false),
2303            (r"a\\_c%", r"\\_", false),
2304            (r"", r"__", false),
2305            (r"\", r"__", false),
2306            (r"\\", r"__", true),
2307            (r"\\\", r"__", false),
2308            (r"\\\\", r"__", false),
2309            (r"a", r"__", false),
2310            (r"\a", r"__", true),
2311            (r"\\a", r"__", false),
2312            (r"%", r"__", false),
2313            (r"\%", r"__", true),
2314            (r"\\%", r"__", false),
2315            (r"%%", r"__", true),
2316            (r"\%%", r"__", false),
2317            (r"\\%%", r"__", false),
2318            (r"_", r"__", false),
2319            (r"\_", r"__", true),
2320            (r"\\_", r"__", false),
2321            (r"__", r"__", true),
2322            (r"\__", r"__", false),
2323            (r"\\__", r"__", false),
2324            (r"abc", r"__", false),
2325            (r"a_c", r"__", false),
2326            (r"a\bc", r"__", false),
2327            (r"a\_c", r"__", false),
2328            (r"%abc", r"__", false),
2329            (r"\%abc", r"__", false),
2330            (r"a\\_c%", r"__", false),
2331            (r"", r"\__", false),
2332            (r"\", r"\__", false),
2333            (r"\\", r"\__", false),
2334            (r"\\\", r"\__", false),
2335            (r"\\\\", r"\__", false),
2336            (r"a", r"\__", false),
2337            (r"\a", r"\__", false),
2338            (r"\\a", r"\__", false),
2339            (r"%", r"\__", false),
2340            (r"\%", r"\__", false),
2341            (r"\\%", r"\__", false),
2342            (r"%%", r"\__", false),
2343            (r"\%%", r"\__", false),
2344            (r"\\%%", r"\__", false),
2345            (r"_", r"\__", false),
2346            (r"\_", r"\__", false),
2347            (r"\\_", r"\__", false),
2348            (r"__", r"\__", true),
2349            (r"\__", r"\__", false),
2350            (r"\\__", r"\__", false),
2351            (r"abc", r"\__", false),
2352            (r"a_c", r"\__", false),
2353            (r"a\bc", r"\__", false),
2354            (r"a\_c", r"\__", false),
2355            (r"%abc", r"\__", false),
2356            (r"\%abc", r"\__", false),
2357            (r"a\\_c%", r"\__", false),
2358            (r"", r"\\__", false),
2359            (r"\", r"\\__", false),
2360            (r"\\", r"\\__", false),
2361            (r"\\\", r"\\__", true),
2362            (r"\\\\", r"\\__", false),
2363            (r"a", r"\\__", false),
2364            (r"\a", r"\\__", false),
2365            (r"\\a", r"\\__", true),
2366            (r"%", r"\\__", false),
2367            (r"\%", r"\\__", false),
2368            (r"\\%", r"\\__", true),
2369            (r"%%", r"\\__", false),
2370            (r"\%%", r"\\__", true),
2371            (r"\\%%", r"\\__", false),
2372            (r"_", r"\\__", false),
2373            (r"\_", r"\\__", false),
2374            (r"\\_", r"\\__", true),
2375            (r"__", r"\\__", false),
2376            (r"\__", r"\\__", true),
2377            (r"\\__", r"\\__", false),
2378            (r"abc", r"\\__", false),
2379            (r"a_c", r"\\__", false),
2380            (r"a\bc", r"\\__", false),
2381            (r"a\_c", r"\\__", false),
2382            (r"%abc", r"\\__", false),
2383            (r"\%abc", r"\\__", false),
2384            (r"a\\_c%", r"\\__", false),
2385            (r"", r"abc", false),
2386            (r"\", r"abc", false),
2387            (r"\\", r"abc", false),
2388            (r"\\\", r"abc", false),
2389            (r"\\\\", r"abc", false),
2390            (r"a", r"abc", false),
2391            (r"\a", r"abc", false),
2392            (r"\\a", r"abc", false),
2393            (r"%", r"abc", false),
2394            (r"\%", r"abc", false),
2395            (r"\\%", r"abc", false),
2396            (r"%%", r"abc", false),
2397            (r"\%%", r"abc", false),
2398            (r"\\%%", r"abc", false),
2399            (r"_", r"abc", false),
2400            (r"\_", r"abc", false),
2401            (r"\\_", r"abc", false),
2402            (r"__", r"abc", false),
2403            (r"\__", r"abc", false),
2404            (r"\\__", r"abc", false),
2405            (r"abc", r"abc", true),
2406            (r"a_c", r"abc", false),
2407            (r"a\bc", r"abc", false),
2408            (r"a\_c", r"abc", false),
2409            (r"%abc", r"abc", false),
2410            (r"\%abc", r"abc", false),
2411            (r"a\\_c%", r"abc", false),
2412            (r"", r"a_c", false),
2413            (r"\", r"a_c", false),
2414            (r"\\", r"a_c", false),
2415            (r"\\\", r"a_c", false),
2416            (r"\\\\", r"a_c", false),
2417            (r"a", r"a_c", false),
2418            (r"\a", r"a_c", false),
2419            (r"\\a", r"a_c", false),
2420            (r"%", r"a_c", false),
2421            (r"\%", r"a_c", false),
2422            (r"\\%", r"a_c", false),
2423            (r"%%", r"a_c", false),
2424            (r"\%%", r"a_c", false),
2425            (r"\\%%", r"a_c", false),
2426            (r"_", r"a_c", false),
2427            (r"\_", r"a_c", false),
2428            (r"\\_", r"a_c", false),
2429            (r"__", r"a_c", false),
2430            (r"\__", r"a_c", false),
2431            (r"\\__", r"a_c", false),
2432            (r"abc", r"a_c", true),
2433            (r"a_c", r"a_c", true),
2434            (r"a\bc", r"a_c", false),
2435            (r"a\_c", r"a_c", false),
2436            (r"%abc", r"a_c", false),
2437            (r"\%abc", r"a_c", false),
2438            (r"a\\_c%", r"a_c", false),
2439            (r"", r"a\bc", false),
2440            (r"\", r"a\bc", false),
2441            (r"\\", r"a\bc", false),
2442            (r"\\\", r"a\bc", false),
2443            (r"\\\\", r"a\bc", false),
2444            (r"a", r"a\bc", false),
2445            (r"\a", r"a\bc", false),
2446            (r"\\a", r"a\bc", false),
2447            (r"%", r"a\bc", false),
2448            (r"\%", r"a\bc", false),
2449            (r"\\%", r"a\bc", false),
2450            (r"%%", r"a\bc", false),
2451            (r"\%%", r"a\bc", false),
2452            (r"\\%%", r"a\bc", false),
2453            (r"_", r"a\bc", false),
2454            (r"\_", r"a\bc", false),
2455            (r"\\_", r"a\bc", false),
2456            (r"__", r"a\bc", false),
2457            (r"\__", r"a\bc", false),
2458            (r"\\__", r"a\bc", false),
2459            (r"abc", r"a\bc", true),
2460            (r"a_c", r"a\bc", false),
2461            (r"a\bc", r"a\bc", false),
2462            (r"a\_c", r"a\bc", false),
2463            (r"%abc", r"a\bc", false),
2464            (r"\%abc", r"a\bc", false),
2465            (r"a\\_c%", r"a\bc", false),
2466            (r"", r"a\_c", false),
2467            (r"\", r"a\_c", false),
2468            (r"\\", r"a\_c", false),
2469            (r"\\\", r"a\_c", false),
2470            (r"\\\\", r"a\_c", false),
2471            (r"a", r"a\_c", false),
2472            (r"\a", r"a\_c", false),
2473            (r"\\a", r"a\_c", false),
2474            (r"%", r"a\_c", false),
2475            (r"\%", r"a\_c", false),
2476            (r"\\%", r"a\_c", false),
2477            (r"%%", r"a\_c", false),
2478            (r"\%%", r"a\_c", false),
2479            (r"\\%%", r"a\_c", false),
2480            (r"_", r"a\_c", false),
2481            (r"\_", r"a\_c", false),
2482            (r"\\_", r"a\_c", false),
2483            (r"__", r"a\_c", false),
2484            (r"\__", r"a\_c", false),
2485            (r"\\__", r"a\_c", false),
2486            (r"abc", r"a\_c", false),
2487            (r"a_c", r"a\_c", true),
2488            (r"a\bc", r"a\_c", false),
2489            (r"a\_c", r"a\_c", false),
2490            (r"%abc", r"a\_c", false),
2491            (r"\%abc", r"a\_c", false),
2492            (r"a\\_c%", r"a\_c", false),
2493            (r"", r"%abc", false),
2494            (r"\", r"%abc", false),
2495            (r"\\", r"%abc", false),
2496            (r"\\\", r"%abc", false),
2497            (r"\\\\", r"%abc", false),
2498            (r"a", r"%abc", false),
2499            (r"\a", r"%abc", false),
2500            (r"\\a", r"%abc", false),
2501            (r"%", r"%abc", false),
2502            (r"\%", r"%abc", false),
2503            (r"\\%", r"%abc", false),
2504            (r"%%", r"%abc", false),
2505            (r"\%%", r"%abc", false),
2506            (r"\\%%", r"%abc", false),
2507            (r"_", r"%abc", false),
2508            (r"\_", r"%abc", false),
2509            (r"\\_", r"%abc", false),
2510            (r"__", r"%abc", false),
2511            (r"\__", r"%abc", false),
2512            (r"\\__", r"%abc", false),
2513            (r"abc", r"%abc", true),
2514            (r"a_c", r"%abc", false),
2515            (r"a\bc", r"%abc", false),
2516            (r"a\_c", r"%abc", false),
2517            (r"%abc", r"%abc", true),
2518            (r"\%abc", r"%abc", true),
2519            (r"a\\_c%", r"%abc", false),
2520            (r"", r"\%abc", false),
2521            (r"\", r"\%abc", false),
2522            (r"\\", r"\%abc", false),
2523            (r"\\\", r"\%abc", false),
2524            (r"\\\\", r"\%abc", false),
2525            (r"a", r"\%abc", false),
2526            (r"\a", r"\%abc", false),
2527            (r"\\a", r"\%abc", false),
2528            (r"%", r"\%abc", false),
2529            (r"\%", r"\%abc", false),
2530            (r"\\%", r"\%abc", false),
2531            (r"%%", r"\%abc", false),
2532            (r"\%%", r"\%abc", false),
2533            (r"\\%%", r"\%abc", false),
2534            (r"_", r"\%abc", false),
2535            (r"\_", r"\%abc", false),
2536            (r"\\_", r"\%abc", false),
2537            (r"__", r"\%abc", false),
2538            (r"\__", r"\%abc", false),
2539            (r"\\__", r"\%abc", false),
2540            (r"abc", r"\%abc", false),
2541            (r"a_c", r"\%abc", false),
2542            (r"a\bc", r"\%abc", false),
2543            (r"a\_c", r"\%abc", false),
2544            (r"%abc", r"\%abc", true),
2545            (r"\%abc", r"\%abc", false),
2546            (r"a\\_c%", r"\%abc", false),
2547            (r"", r"a\\_c%", false),
2548            (r"\", r"a\\_c%", false),
2549            (r"\\", r"a\\_c%", false),
2550            (r"\\\", r"a\\_c%", false),
2551            (r"\\\\", r"a\\_c%", false),
2552            (r"a", r"a\\_c%", false),
2553            (r"\a", r"a\\_c%", false),
2554            (r"\\a", r"a\\_c%", false),
2555            (r"%", r"a\\_c%", false),
2556            (r"\%", r"a\\_c%", false),
2557            (r"\\%", r"a\\_c%", false),
2558            (r"%%", r"a\\_c%", false),
2559            (r"\%%", r"a\\_c%", false),
2560            (r"\\%%", r"a\\_c%", false),
2561            (r"_", r"a\\_c%", false),
2562            (r"\_", r"a\\_c%", false),
2563            (r"\\_", r"a\\_c%", false),
2564            (r"__", r"a\\_c%", false),
2565            (r"\__", r"a\\_c%", false),
2566            (r"\\__", r"a\\_c%", false),
2567            (r"abc", r"a\\_c%", false),
2568            (r"a_c", r"a\\_c%", false),
2569            (r"a\bc", r"a\\_c%", true),
2570            (r"a\_c", r"a\\_c%", true),
2571            (r"%abc", r"a\\_c%", false),
2572            (r"\%abc", r"a\\_c%", false),
2573            (r"a\\_c%", r"a\\_c%", false),
2574        ];
2575
2576        let values = test_cases
2577            .iter()
2578            .map(|(value, _, _)| *value)
2579            .collect::<Vec<_>>();
2580        let patterns = test_cases
2581            .iter()
2582            .map(|(_, pattern, _)| *pattern)
2583            .collect::<Vec<_>>();
2584        let expected = BooleanArray::from(
2585            test_cases
2586                .iter()
2587                .map(|(_, _, expected)| *expected)
2588                .collect::<Vec<_>>(),
2589        );
2590        let unexpected = BooleanArray::from(
2591            test_cases
2592                .iter()
2593                .map(|(_, _, expected)| !*expected)
2594                .collect::<Vec<_>>(),
2595        );
2596
2597        for string_type in [DataType::Utf8, DataType::LargeUtf8, DataType::Utf8View] {
2598            let values = make_array(values.iter(), &string_type);
2599            let patterns = make_array(patterns.iter(), &string_type);
2600            let (values, patterns) = (values.as_ref(), patterns.as_ref());
2601
2602            assert_eq!(like(&values, &patterns).unwrap(), expected,);
2603            assert_eq!(ilike(&values, &patterns).unwrap(), expected,);
2604            assert_eq!(nlike(&values, &patterns).unwrap(), unexpected,);
2605            assert_eq!(nilike(&values, &patterns).unwrap(), unexpected,);
2606        }
2607    }
2608
2609    fn make_datums(
2610        value: impl AsRef<str>,
2611        data_type: &DataType,
2612    ) -> Vec<(Box<dyn Datum>, DatumType)> {
2613        match data_type {
2614            DataType::Utf8 => {
2615                let array = StringArray::from_iter_values([value]);
2616                vec![
2617                    (Box::new(array.clone()), DatumType::Array),
2618                    (Box::new(Scalar::new(array)), DatumType::Scalar),
2619                ]
2620            }
2621            DataType::LargeUtf8 => {
2622                let array = LargeStringArray::from_iter_values([value]);
2623                vec![
2624                    (Box::new(array.clone()), DatumType::Array),
2625                    (Box::new(Scalar::new(array)), DatumType::Scalar),
2626                ]
2627            }
2628            DataType::Utf8View => {
2629                let array = StringViewArray::from_iter_values([value]);
2630                vec![
2631                    (Box::new(array.clone()), DatumType::Array),
2632                    (Box::new(Scalar::new(array)), DatumType::Scalar),
2633                ]
2634            }
2635            _ => unimplemented!(),
2636        }
2637    }
2638
2639    fn make_array(
2640        values: impl IntoIterator<Item: AsRef<str>>,
2641        data_type: &DataType,
2642    ) -> Box<dyn Array> {
2643        match data_type {
2644            DataType::Utf8 => Box::new(StringArray::from_iter_values(values)),
2645            DataType::LargeUtf8 => Box::new(LargeStringArray::from_iter_values(values)),
2646            DataType::Utf8View => Box::new(StringViewArray::from_iter_values(values)),
2647            _ => unimplemented!(),
2648        }
2649    }
2650
2651    #[derive(Debug)]
2652    enum DatumType {
2653        Array,
2654        Scalar,
2655    }
2656}