API: Fix Identity projection for mismatched transform types (#15502)#16074
Open
yadavay-amzn wants to merge 1 commit intoapache:mainfrom
Open
API: Fix Identity projection for mismatched transform types (#15502)#16074yadavay-amzn wants to merge 1 commit intoapache:mainfrom
yadavay-amzn wants to merge 1 commit intoapache:mainfrom
Conversation
ebyhr
reviewed
Apr 22, 2026
| @Test | ||
| public void testIdentityProjectionWithTransformPredicate() { | ||
| // Regression test for https://github.com/apache/iceberg/issues/15502 | ||
| // Identity-partitioned timestamptz field filtered with hours() should not throw |
Member
There was a problem hiding this comment.
This sentence looks incomplete. "... should not throw ValidationException"?
Contributor
Author
There was a problem hiding this comment.
Fixed — completed the sentence.
|
|
||
| // The identity transform cannot project a hours-transform predicate, so it should | ||
| // be replaced with alwaysTrue (inclusive) rather than throwing ValidationException | ||
| assertThat(projected).isEqualTo(Expressions.alwaysTrue()); |
Member
There was a problem hiding this comment.
ValidationException isn't thrown in this test even if I revert a change of Identity.java.
Contributor
Author
There was a problem hiding this comment.
The exception is caught internally by the projection framework and converted to alwaysTrue/alwaysFalse. Without the fix, projectStrict() creates an UnboundPredicate with an integer literal for a timestamptz field, which fails during binding — the test assertion fails because the projection result is neither alwaysTrue nor alwaysFalse. Updated the comments to explain this more clearly.
…5502) Identity.project() and projectStrict() delegate to projectStrict() which creates an unbound predicate with the literal from the input predicate. When the predicate term is a transform (e.g. hours(ts) = 490674), the literal type (integer) does not match the partition field type (timestamptz), causing a ValidationException when the unbound predicate is later bound to the partition schema. Fix: Return null from projectStrict() when the predicate term is not a BoundReference, indicating the identity transform cannot project transform-based predicates. This causes the projection to fall back to alwaysTrue (inclusive) or alwaysFalse (strict), which is correct.
72461b2 to
a078b0f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #15502
Problem
When an Iceberg table has manifests written using a partition spec with
identity-transformed timestamp field, queries that filter on that field using a temporal transform likehours()fail with:Identity.projectStrict()creates an unbound predicate with the literal from the input predicate. When the predicate term is a transform (e.g.hours(ts) = 490674), the literal type (integer) does not match the partition field type (timestamptz), causing aValidationExceptionwhen the unbound predicate is later bound to the partition schema.Fix
Return
nullfromprojectStrict()when the predicate term is not aBoundReference, indicating the identity transform cannot project transform-based predicates. This causes the projection to fall back toalwaysTrue(inclusive) oralwaysFalse(strict), which is the correct behavior.The fix is a 4-line guard clause at the top of
projectStrict(). Sinceproject()delegates toprojectStrict(), both paths are covered.Testing
Added a regression test in
TestProjectionthat reproduces the exact scenario from the issue: identity-partitionedtimestamptzfield filtered withhours()transform, verifying both inclusive and strict projections.