func()

in table/evaluators.go [1133:1186]


func (m *inclusiveMetricsEval) VisitNotStartsWith(t iceberg.BoundTerm, lit iceberg.Literal) bool {
	field := t.Ref().Field()
	fieldID := field.ID

	if m.mayContainNull(fieldID) {
		return rowsMightMatch
	}

	if _, ok := field.Type.(iceberg.PrimitiveType); !ok {
		panic(fmt.Errorf("%w: expected iceberg.PrimitiveType, got %s",
			iceberg.ErrInvalidTypeString, field.Type))
	}

	// 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
	lowerBoundBytes, upperBoundBytes := m.lowerBounds[fieldID], m.upperBounds[fieldID]
	if lowerBoundBytes != nil && upperBoundBytes != nil {
		lowerBound, err := iceberg.LiteralFromBytes(field.Type, lowerBoundBytes)
		if err != nil {
			panic(err)
		}

		upperBound, err := iceberg.LiteralFromBytes(field.Type, upperBoundBytes)
		if err != nil {
			panic(err)
		}

		var prefix, lower, upper string
		if val, ok := lit.(iceberg.TypedLiteral[string]); ok {
			prefix = val.Value()
			lower, upper = lowerBound.(iceberg.TypedLiteral[string]).Value(), upperBound.(iceberg.TypedLiteral[string]).Value()
		} else {
			prefix = string(lit.(iceberg.TypedLiteral[[]byte]).Value())
			lower, upper = string(lowerBound.(iceberg.TypedLiteral[[]byte]).Value()), string(upperBound.(iceberg.TypedLiteral[[]byte]).Value())
		}

		lenPrefix := len(prefix)
		if len(lower) < lenPrefix {
			return rowsMightMatch
		}

		if lower[:lenPrefix] == prefix {
			if len(upper) < lenPrefix {
				return rowsMightMatch
			}

			if upper[:lenPrefix] == prefix {
				return rowsCannotMatch
			}
		}
	}

	return rowsMightMatch
}