fn apply()

in arrow-ord/src/cmp.rs [329:382]


fn apply<T: ArrayOrd>(
    op: Op,
    l: T,
    l_s: bool,
    l_v: Option<&dyn AnyDictionaryArray>,
    r: T,
    r_s: bool,
    r_v: Option<&dyn AnyDictionaryArray>,
) -> Option<BooleanBuffer> {
    if l.len() == 0 || r.len() == 0 {
        return None; // Handle empty dictionaries
    }

    if !l_s && !r_s && (l_v.is_some() || r_v.is_some()) {
        // Not scalar and at least one side has a dictionary, need to perform vectored comparison
        let l_v = l_v
            .map(|x| x.normalized_keys())
            .unwrap_or_else(|| (0..l.len()).collect());

        let r_v = r_v
            .map(|x| x.normalized_keys())
            .unwrap_or_else(|| (0..r.len()).collect());

        assert_eq!(l_v.len(), r_v.len()); // Sanity check

        Some(match op {
            Op::Equal | Op::NotDistinct => apply_op_vectored(l, &l_v, r, &r_v, false, T::is_eq),
            Op::NotEqual | Op::Distinct => apply_op_vectored(l, &l_v, r, &r_v, true, T::is_eq),
            Op::Less => apply_op_vectored(l, &l_v, r, &r_v, false, T::is_lt),
            Op::LessEqual => apply_op_vectored(r, &r_v, l, &l_v, true, T::is_lt),
            Op::Greater => apply_op_vectored(r, &r_v, l, &l_v, false, T::is_lt),
            Op::GreaterEqual => apply_op_vectored(l, &l_v, r, &r_v, true, T::is_lt),
        })
    } else {
        let l_s = l_s.then(|| l_v.map(|x| x.normalized_keys()[0]).unwrap_or_default());
        let r_s = r_s.then(|| r_v.map(|x| x.normalized_keys()[0]).unwrap_or_default());

        let buffer = match op {
            Op::Equal | Op::NotDistinct => apply_op(l, l_s, r, r_s, false, T::is_eq),
            Op::NotEqual | Op::Distinct => apply_op(l, l_s, r, r_s, true, T::is_eq),
            Op::Less => apply_op(l, l_s, r, r_s, false, T::is_lt),
            Op::LessEqual => apply_op(r, r_s, l, l_s, true, T::is_lt),
            Op::Greater => apply_op(r, r_s, l, l_s, false, T::is_lt),
            Op::GreaterEqual => apply_op(l, l_s, r, r_s, true, T::is_lt),
        };

        // If a side had a dictionary, and was not scalar, we need to materialize this
        Some(match (l_v, r_v) {
            (Some(l_v), _) if l_s.is_none() => take_bits(l_v, buffer),
            (_, Some(r_v)) if r_s.is_none() => take_bits(r_v, buffer),
            _ => buffer,
        })
    }
}