fn not_starts_with()

in crates/iceberg/src/expr/visitors/manifest_evaluator.rs [287:344]


    fn not_starts_with(
        &mut self,
        reference: &BoundReference,
        datum: &Datum,
        _predicate: &BoundPredicate,
    ) -> crate::Result<bool> {
        let field = self.field_summary_for_reference(reference);

        if field.contains_null || field.lower_bound.is_none() || field.upper_bound.is_none() {
            return ROWS_MIGHT_MATCH;
        }

        let prefix = ManifestFilterVisitor::datum_as_str(
            datum,
            "Cannot perform not_starts_with on non-string value",
        )?;
        let prefix_len = prefix.len();

        // not_starts_with will match unless all values must start with the prefix. This happens when
        // the lower and upper bounds both start with the prefix.
        if let Some(lower_bound) = &field.lower_bound {
            let lower_bound_str = ManifestFilterVisitor::datum_as_str(
                lower_bound,
                "Cannot perform not_starts_with on non-string lower bound",
            )?;

            // if lower is shorter than the prefix then lower doesn't start with the prefix
            if prefix_len > lower_bound_str.len() {
                return ROWS_MIGHT_MATCH;
            }

            if prefix
                .as_bytes()
                .eq(&lower_bound_str.as_bytes()[..prefix_len])
            {
                if let Some(upper_bound) = &field.upper_bound {
                    let upper_bound_str = ManifestFilterVisitor::datum_as_str(
                        upper_bound,
                        "Cannot perform not_starts_with on non-string upper bound",
                    )?;

                    // if upper is shorter than the prefix then upper can't start with the prefix
                    if prefix_len > upper_bound_str.len() {
                        return ROWS_MIGHT_MATCH;
                    }

                    if prefix
                        .as_bytes()
                        .eq(&upper_bound_str.as_bytes()[..prefix_len])
                    {
                        return ROWS_CANNOT_MATCH;
                    }
                }
            }
        }

        ROWS_MIGHT_MATCH
    }