This is an automated email from the ASF dual-hosted git repository.
CTTY pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-rust.git
The following commit(s) were added to refs/heads/main by this push:
new aa58d2fdd feat(partition): adjust transform boundary for timestamp
types (#2422)
aa58d2fdd is described below
commit aa58d2fdde4516cd6c1081d5c43c42dde6775955
Author: dentiny <[email protected]>
AuthorDate: Tue May 19 15:46:17 2026 -0700
feat(partition): adjust transform boundary for timestamp types (#2422)
## Which issue does this PR close?
- Closes https://github.com/apache/iceberg-rust/issues/2421
## What changes are included in this PR?
This PR implements boundary adjustment for timestamp types, which could
potentially avoid scan unnecessary extra partition; hopefully my issue
description is clear enough.
## Are these changes tested?
Yes.
---
crates/iceberg/src/spec/transform.rs | 58 ++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/crates/iceberg/src/spec/transform.rs
b/crates/iceberg/src/spec/transform.rs
index 73fd290ee..97ab638e7 100644
--- a/crates/iceberg/src/spec/transform.rs
+++ b/crates/iceberg/src/spec/transform.rs
@@ -667,6 +667,15 @@ impl Transform {
(PrimitiveType::Timestamp, PrimitiveLiteral::Long(v)) => {
Some(Datum::timestamp_micros(v - 1))
}
+ (PrimitiveType::Timestamptz, PrimitiveLiteral::Long(v)) => {
+ Some(Datum::timestamptz_micros(v - 1))
+ }
+ (PrimitiveType::TimestampNs, PrimitiveLiteral::Long(v)) => {
+ Some(Datum::timestamp_nanos(v - 1))
+ }
+ (PrimitiveType::TimestamptzNs, PrimitiveLiteral::Long(v)) => {
+ Some(Datum::timestamptz_nanos(v - 1))
+ }
_ => Some(datum.to_owned()),
},
PredicateOperator::GreaterThan => match (datum.data_type(),
datum.literal()) {
@@ -679,6 +688,15 @@ impl Transform {
(PrimitiveType::Timestamp, PrimitiveLiteral::Long(v)) => {
Some(Datum::timestamp_micros(v + 1))
}
+ (PrimitiveType::Timestamptz, PrimitiveLiteral::Long(v)) => {
+ Some(Datum::timestamptz_micros(v + 1))
+ }
+ (PrimitiveType::TimestampNs, PrimitiveLiteral::Long(v)) => {
+ Some(Datum::timestamp_nanos(v + 1))
+ }
+ (PrimitiveType::TimestamptzNs, PrimitiveLiteral::Long(v)) => {
+ Some(Datum::timestamptz_nanos(v + 1))
+ }
_ => Some(datum.to_owned()),
},
PredicateOperator::Eq
@@ -1062,3 +1080,43 @@ enum AdjustedProjection {
Single(Datum),
Set(FnvHashSet<Datum>),
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ fn check_boundary(op: PredicateOperator, input: Datum, expected: Datum) {
+ let result = Transform::adjust_boundary(&op, &input).unwrap().unwrap();
+ assert_eq!(result, expected);
+ }
+
+ #[test]
+ fn test_adjust_boundary_timestamp_types() {
+ for (datum, dec, inc) in [
+ (
+ Datum::timestamptz_micros(1000),
+ Datum::timestamptz_micros(999),
+ Datum::timestamptz_micros(1001),
+ ),
+ (
+ Datum::timestamp_nanos(5000),
+ Datum::timestamp_nanos(4999),
+ Datum::timestamp_nanos(5001),
+ ),
+ (
+ Datum::timestamptz_nanos(5000),
+ Datum::timestamptz_nanos(4999),
+ Datum::timestamptz_nanos(5001),
+ ),
+ ] {
+ check_boundary(PredicateOperator::LessThan, datum.clone(), dec);
+ check_boundary(PredicateOperator::GreaterThan, datum.clone(), inc);
+ check_boundary(
+ PredicateOperator::LessThanOrEq,
+ datum.clone(),
+ datum.clone(),
+ );
+ check_boundary(PredicateOperator::GreaterThanOrEq, datum.clone(),
datum);
+ }
+ }
+}