mbutrovich opened a new issue, #3387:
URL: https://github.com/apache/iceberg-rust/issues/3387

   ## Apache Iceberg Rust version
   
   main (b2e90754b1f9eaea741d353d51ae644aa9cef479), also v0.10.1
   
   ## Describe the bug
   
   Format v3 allows promoting `date` to `timestamp` and `timestamp_ns` 
([spec](https://github.com/apache/iceberg/blob/5e7169168db3d34e29354c6f59ec4d6e420b8d2d/format/spec.md?plain=1#L356-L362)).
 Type promotion doesn't rewrite existing bounds, so a reader must decode a 
4-byte bound on a `timestamp` or `timestamp_ns` column as a `date` 
([spec](https://github.com/apache/iceberg/blob/5e7169168db3d34e29354c6f59ec4d6e420b8d2d/format/spec.md?plain=1#L366-L377)).
   
   `Datum::try_from_bytes` reads `timestamp` and `timestamp_ns` bounds only as 
8 bytes 
([`datum.rs#L408-L416`](https://github.com/apache/iceberg-rust/blob/b2e90754b1f9eaea741d353d51ae644aa9cef479/crates/iceberg/src/spec/values/datum.rs#L408-L416)),
 and returns an error for 4 bytes. The `long` arm already handles the 4-byte 
`int` case from the same table 
([`datum.rs#L385-L392`](https://github.com/apache/iceberg-rust/blob/b2e90754b1f9eaea741d353d51ae644aa9cef479/crates/iceberg/src/spec/values/datum.rs#L385-L392)),
 and so does the `double` arm for `float`.
   
   Manifest parsing decodes every bound and returns the first error 
([`_serde.rs#L263-L282`](https://github.com/apache/iceberg-rust/blob/b2e90754b1f9eaea741d353d51ae644aa9cef479/crates/iceberg/src/spec/manifest/_serde.rs#L263-L282)).
 One such bound fails the whole manifest read, including for scans that don't 
filter on that column.
   
   No writer I know of produces these bounds yet. Java's 
`TypeUtil.isPromotionAllowed` doesn't allow `date` to `timestamp` 
([`TypeUtil.java#L471-L497`](https://github.com/apache/iceberg/blob/5e7169168db3d34e29354c6f59ec4d6e420b8d2d/api/src/main/java/org/apache/iceberg/types/TypeUtil.java#L471-L497)),
 and neither do PyIceberg or iceberg-rust's `UpdateSchemaAction`. The read 
fails as soon as an engine implements the promotion.
   
   ## To Reproduce
   
   ```rust
   use iceberg::spec::{Datum, PrimitiveType};
   
   // 2026-10-09, written while the column was a `date`.
   let bytes = 20_735i32.to_le_bytes();
   
   // Err(DataInvalid => failed to convert byte slice to array)
   Datum::try_from_bytes(&bytes, PrimitiveType::Timestamp);
   // Err(DataInvalid => failed to convert byte slice to array)
   Datum::try_from_bytes(&bytes, PrimitiveType::TimestampNs);
   ```
   
   ## Expected behavior
   
   A 4-byte bound on a `timestamp` column decodes as a `date` and converts to 
microseconds since the epoch (days times 86,400,000,000). On a `timestamp_ns` 
column it converts to nanoseconds (days times 86,400,000,000,000). A day count 
whose product doesn't fit in an `i64` returns an error, because the spec 
requires values outside the promoted type's range to fail at runtime. A 4-byte 
bound on `timestamptz` or `timestamptz_ns` stays an error, since the spec 
doesn't allow promoting `date` to those types.
   
   ## Willingness to contribute
   
   I can contribute a fix for this bug independently
   


-- 
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