in table/evaluators.go [1062:1131]
func (m *inclusiveMetricsEval) VisitStartsWith(t iceberg.BoundTerm, lit iceberg.Literal) bool {
field := t.Ref().Field()
fieldID := field.ID
if m.containsNullsOnly(fieldID) {
return rowsCannotMatch
}
if _, ok := field.Type.(iceberg.PrimitiveType); !ok {
panic(fmt.Errorf("%w: expected iceberg.PrimitiveType, got %s",
iceberg.ErrInvalidTypeString, field.Type))
}
var prefix string
if val, ok := lit.(iceberg.TypedLiteral[string]); ok {
prefix = val.Value()
} else {
prefix = string(lit.(iceberg.TypedLiteral[[]byte]).Value())
}
lenPrefix := len(prefix)
if lowerBoundBytes := m.lowerBounds[fieldID]; lowerBoundBytes != nil {
lowerBound, err := iceberg.LiteralFromBytes(field.Type, lowerBoundBytes)
if err != nil {
panic(err)
}
var v string
switch l := lowerBound.(type) {
case iceberg.TypedLiteral[string]:
v = l.Value()
case iceberg.TypedLiteral[[]byte]:
v = string(l.Value())
}
if len(v) > lenPrefix {
v = v[:lenPrefix]
}
if len(v) > 0 && v > prefix {
return rowsCannotMatch
}
}
if upperBoundBytes := m.upperBounds[fieldID]; upperBoundBytes != nil {
upperBound, err := iceberg.LiteralFromBytes(field.Type, upperBoundBytes)
if err != nil {
panic(err)
}
var v string
switch u := upperBound.(type) {
case iceberg.TypedLiteral[string]:
v = u.Value()
case iceberg.TypedLiteral[[]byte]:
v = string(u.Value())
}
if len(v) > lenPrefix {
v = v[:lenPrefix]
}
if len(v) > 0 && v < prefix {
return rowsCannotMatch
}
}
return rowsMightMatch
}