wirybeaver commented on code in PR #3342:
URL: https://github.com/apache/iceberg-rust/pull/3342#discussion_r4462066136


##########
crates/iceberg/src/writer/file_writer/parquet_writer.rs:
##########
@@ -401,8 +489,48 @@ impl MinMaxColAggregator {
         Ok(())
     }
 
+    fn update_geo(&mut self, field_id: i32, column: &ColumnChunkMetaData) {
+        // Null-only row groups do not contribute coordinates and need no 
bounding box.
+        if column.num_values() == 0
+            || column
+                .statistics()
+                .and_then(Statistics::null_count_opt)
+                .is_some_and(|nulls| nulls == column.num_values() as u64)
+        {
+            return;
+        }
+        let bbox = column
+            .geo_statistics()
+            .and_then(|stats| stats.bounding_box());
+        self.geo_bounds
+            .entry(field_id)
+            .and_modify(|state| {
+                if let (Some(bounds), Some(bbox)) = (state.as_mut(), bbox) {
+                    bounds.merge(bbox);
+                } else {
+                    *state = None;
+                }
+            })
+            .or_insert_with(|| bbox.map(GeospatialBounds::from));
+    }
+
     /// Returns lower and upper bounds
-    fn produce(self) -> (HashMap<i32, Datum>, HashMap<i32, Datum>) {
+    fn produce(mut self) -> (HashMap<i32, Datum>, HashMap<i32, Datum>) {
+        for (field_id, bounds) in self.geo_bounds {
+            if let Some(bounds) = bounds {
+                let ty = self
+                    .schema
+                    .field_by_id(field_id)
+                    .unwrap()
+                    .field_type
+                    .as_primitive_type()
+                    .unwrap()
+                    .clone();
+                let (lower, upper) = bounds.into_datums(ty);

Review Comment:
   Addressed in 88ce4168. Each geometry bounds entry now carries its 
PrimitiveType with the accumulated bounds. produce() uses that stored type 
directly; it no longer looks the field up in the schema again.



##########
crates/iceberg/src/writer/file_writer/parquet_writer.rs:
##########
@@ -2570,11 +2703,252 @@ mod tests {
             (
                 parquet::basic::Type::FIXED_LEN_BYTE_ARRAY,
                 16,
-                Some(&parquet::basic::LogicalType::Uuid)
+                Some(&LogicalType::Uuid)
             )
         );
     }
 
+    #[tokio::test]
+    async fn test_geospatial_write_roundtrip() -> Result<()> {

Review Comment:
   Addressed in 88ce4168. Split the long lifecycle test into named Parquet 
payload/metadata round-trip, manifest bounds round-trip, and scalar-metrics 
safety tests, sharing one file fixture. Added focused XY, XYZ, and 
wrapping-geometry serialization tests; the wrapping case checks 
negative/positive infinity for X. Missing statistics and null-only row groups 
have separate, small aggregation scenarios.



##########
crates/iceberg/src/writer/file_writer/parquet_writer.rs:
##########
@@ -364,13 +443,22 @@ impl MinMaxColAggregator {
             // Ignore the field if it is not in schema.
             return Ok(());
         };
-        let Type::Primitive(ty) = ty.clone() else {
+        let Type::Primitive(ty) = ty else {
             return Err(Error::new(
                 ErrorKind::Unexpected,
                 format!("Composed type {ty} is not supported for min max 
aggregation."),
             ));
         };
 
+        if matches!(ty, PrimitiveType::Geometry(_) | 
PrimitiveType::Geography(_)) {

Review Comment:
   Agreed on keeping the scope to Geometry. In 88ce4168, only Geometry consumes 
Parquet bounding boxes; Geography returns without producing lower/upper bounds, 
even when its column metadata includes geo_statistics. Removed the geography 
union/normalization path and added a regression test for that omission. 
Geography payload and logical metadata writing remain covered by the Parquet 
round-trip test.



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