zeroshade commented on code in PR #1679:
URL: https://github.com/apache/iceberg-go/pull/1679#discussion_r3832049802


##########
exprs.go:
##########
@@ -790,7 +788,7 @@ type BoundLiteralPredicate interface {
 
 func newBoundLiteralPredicate[T LiteralType](op Operation, term BoundTerm, lit 
Literal) BoundPredicate {
        return &boundLiteralPredicate[T]{
-               op: op, term: term.(bound[T]),
+               op: op, term: term,

Review Comment:
   **Blocking:** allowing a `BoundTransform` here exposes it to metrics and 
bloom evaluators that still compare the transform-result literal with raw 
source-column values from `term.Ref()`. I reproduced `truncate[3](category) == 
"boo"` incorrectly pruning a file containing `"books"`. More seriously, strict 
metrics reports that every row matches `truncate[3](category) != "boo"` for a 
required file containing only `"books"`, even though no row matches; filtered 
deletion can therefore drop the entire file. Bloom pruning has the same 
source-domain/transformed-domain mismatch. Please make all source-column 
pruning consumers conservatively handle transformed terms or correctly 
transform their statistics.



##########
exprs.go:
##########
@@ -838,7 +836,7 @@ func createBoundLiteralPredicate(op Operation, term 
BoundTerm, lit Literal) (Bou
 
 type boundLiteralPredicate[T LiteralType] struct {
        op   Operation
-       term bound[T]
+       term BoundTerm

Review Comment:
   **Blocking:** the Substrait converter is not transform-aware. Its reference, 
literal, and set helpers all emit `term.Ref()` directly, so 
`truncate[3](category) == "boo"` becomes `category == "boo"`, silently changing 
the predicate. Bucket and temporal transforms can instead fail because the 
source and result types differ. This path is used by scan filtering and 
partial-file rewrites; please encode the transform in Substrait or reject 
transformed predicates there rather than dropping it.



##########
visitors.go:
##########
@@ -406,8 +406,23 @@ func nullsFirstCmp[T LiteralType](cmp Comparator[T], v1, 
v2 Optional[T]) int {
        return cmp(v1.Val, v2.Val)
 }
 
+func typedTermEval[T LiteralType](st StructLike, term BoundTerm) Optional[T] {
+       v := term.evalToLiteral(st)
+       if !v.Valid {
+               return Optional[T]{}
+       }
+
+       lit, ok := v.Val.(TypedLiteral[T])

Review Comment:
   **Major:** this assertion makes `day` predicates unevaluable. 
`DayTransform.ResultType` is `Date`, so binding selects `TypedLiteral[Date]`, 
but `DayTransform.Apply` returns an `Int32Literal`. A direct `day(ts) == 
Date(0)` evaluation returns `type error: ... evaluated to literal type int, 
expected date`. Please align the transform's evaluated literal with its 
declared result type (and add coverage for `day` alongside bucket/truncate).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to