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


##########
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:
   Can we break this down into multiple tests? currently it's kinda hard to 
read and understand what exact case do we cover here
   
   Also I noticed some cases are not really covered. I asked my agent to come 
up with more testing cases:
   - Check plain XY and XYZ bounds
   - Wrapping geometry box turns into +inf/-inf



##########
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:
   It feels off that we have to find the ty again, can we carry the type along 
with the geo_bound state?
   
   



##########
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:
   I have some concerns about handling geography data here. After some 
investigation, it looks like on the Java side people have already discussed the 
same before and the result is: We cannot trust any geography vertexes to use 
them to draw bounding boxes for geography data because they may not include the 
edges: 
https://github.com/apache/iceberg/blob/main/core/src/main/java/org/apache/iceberg/GeometryBoundsBuilder.java#L39-L42
   
   I think it would be safer to only update_geo for Geometry data, and leave 
geography unhandled for now



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