in pyiceberg/expressions/visitors.py [0:0]
def visit_not_starts_with(self, term: BoundTerm[L], literal: Literal[L]) -> bool:
pos = term.ref().accessor.position
field = self.partition_fields[pos]
prefix = str(literal.value)
len_prefix = len(prefix)
if field.contains_null or field.lower_bound is None or field.upper_bound is None:
return ROWS_MIGHT_MATCH
# 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.
lower = _from_byte_buffer(term.ref().field.field_type, field.lower_bound)
upper = _from_byte_buffer(term.ref().field.field_type, field.upper_bound)
if lower is not None and upper is not None:
# if lower is shorter than the prefix then lower doesn't start with the prefix
if len(lower) < len_prefix:
return ROWS_MIGHT_MATCH
if lower[:len_prefix] == prefix:
# if upper is shorter than the prefix then upper can't start with the prefix
if len(upper) < len_prefix:
return ROWS_MIGHT_MATCH
if upper[:len_prefix] == prefix:
return ROWS_CANNOT_MATCH
return ROWS_MIGHT_MATCH