1use 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
59pub fn like(left: &dyn Datum, right: &dyn Datum) -> Result<BooleanArray, ArrowError> {
84 like_op(Op::Like(false), left, right)
85}
86
87pub fn ilike(left: &dyn Datum, right: &dyn Datum) -> Result<BooleanArray, ArrowError> {
95 like_op(Op::ILike(false), left, right)
96}
97
98pub fn nlike(left: &dyn Datum, right: &dyn Datum) -> Result<BooleanArray, ArrowError> {
104 like_op(Op::Like(true), left, right)
105}
106
107pub fn nilike(left: &dyn Datum, right: &dyn Datum) -> Result<BooleanArray, ArrowError> {
113 like_op(Op::ILike(true), left, right)
114}
115
116pub fn starts_with(left: &dyn Datum, right: &dyn Datum) -> Result<BooleanArray, ArrowError> {
139 like_op(Op::StartsWith, left, right)
140}
141
142pub fn ends_with(left: &dyn Datum, right: &dyn Datum) -> Result<BooleanArray, ArrowError> {
165 like_op(Op::EndsWith, left, right)
166}
167
168pub fn contains(left: &dyn Datum, right: &dyn Datum) -> Result<BooleanArray, ArrowError> {
191 like_op(Op::Contains, left, right)
192}
193
194pub 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 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 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 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 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)] 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 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 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)] 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)] 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)] 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)] 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)] 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 test_utf8_scalar!(
1065 #[cfg_attr(miri, ignore)] 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)] 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)] 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)] 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 test_utf8_and_binary_scalar!(
1156 test_utf8_and_binary_array_contains_unicode_contains,
1157 vec![
1158 "sdlkdfFkoßsdfs",
1159 "sdlkdFFkoSSdggs", "sdlkdFFkoSSsdsd", "FkoS",
1162 "Fkos",
1163 "ffkoSS",
1164 "ffkoß",
1165 "😃sadlksFFkoSSsh😃klF", "😱slgFFkoSSsh😃klF", "FFkoSS", "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)] 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 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)] 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)] 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)] 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)] 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 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)] 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)] fn string_null_like_pattern() {
1441 for pattern in &[
1443 "", "_", "%", "a%", "%a", "a%b", "%a%", "%a%b_c_d%e", ] {
1452 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)] fn string_view_null_like_pattern() {
1488 for pattern in &[
1490 "", "_", "%", "a%", "%a", "a%b", "%a%", "%a%b_c_d%e", ] {
1499 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)] fn like_escape() {
1601 let test_cases = vec![
1603 (r"", r"", true),
1605 (r"\", r"", false),
1606 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (r"\\%", r"\\\\\\\%", false),
1775 (r"\\\", r"\\\\\\\%", false),
1776 (r"\\\%", r"\\\\\\\%", true),
1777 (r"\\\\", r"\\\\\\\%", false),
1778 (r"\\\\%", r"\\\\\\\%", false),
1779 (r"\\\\\\\%", r"\\\\\\\%", false),
1780 (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 (r"\\\", r"\\\\\\\\%", false),
1790 (r"\\\\", r"\\\\\\\\%", true),
1791 (r"\\\\\", r"\\\\\\\\%", true),
1792 (r"\\\\xyz", r"\\\\\\\\%", true),
1793 (r"\\\\\\\\%", r"\\\\\\\\%", true),
1794 (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)] fn like_escape_many() {
1843 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}