fn like_scalar_op>()

in arrow-string/src/like.rs [278:323]


fn like_scalar_op<'a, F: Fn(bool) -> bool, L: ArrayAccessor<Item = &'a str>>(
    left: L,
    right: &str,
    op: F,
) -> Result<BooleanArray, ArrowError> {
    if !right.contains(is_like_pattern) {
        // fast path, can use equals
        Ok(BooleanArray::from_unary(left, |item| op(item == right)))
    } else if right.ends_with('%')
        && !right.ends_with("\\%")
        && !right[..right.len() - 1].contains(is_like_pattern)
    {
        // fast path, can use starts_with
        let starts_with = &right[..right.len() - 1];

        Ok(BooleanArray::from_unary(left, |item| {
            op(item.starts_with(starts_with))
        }))
    } else if right.starts_with('%') && !right[1..].contains(is_like_pattern) {
        // fast path, can use ends_with
        let ends_with = &right[1..];

        Ok(BooleanArray::from_unary(left, |item| {
            op(item.ends_with(ends_with))
        }))
    } else if right.starts_with('%')
        && right.ends_with('%')
        && !right.ends_with("\\%")
        && !right[1..right.len() - 1].contains(is_like_pattern)
    {
        let contains = &right[1..right.len() - 1];

        Ok(BooleanArray::from_unary(left, |item| {
            op(item.contains(contains))
        }))
    } else {
        let re_pattern = replace_like_wildcards(right)?;
        let re = Regex::new(&format!("(?s)^{re_pattern}$")).map_err(|e| {
            ArrowError::ComputeError(format!(
                "Unable to build regex from LIKE pattern: {e}"
            ))
        })?;

        Ok(BooleanArray::from_unary(left, |item| op(re.is_match(item))))
    }
}