mbutrovich commented on code in PR #14:
URL: https://github.com/apache/datafusion-iceberg/pull/14#discussion_r4095762047


##########
crates/datafusion/src/physical_plan/project.rs:
##########
@@ -92,38 +88,72 @@ pub fn project_with_partition(
         projection_exprs.push((column_expr, field.name().clone()));
     }
 
-    let partition_expr = Arc::new(PartitionExpr::new(calculator, 
partition_spec.clone()));
+    let partition_expr = Arc::new(PartitionExpr::try_new(
+        partition_spec.clone(),
+        table_schema.clone(),
+    )?);
     projection_exprs.push((partition_expr, 
PROJECTED_PARTITION_VALUE_COLUMN.to_string()));
 
     let projection = ProjectionExec::try_new(projection_exprs, input)?;
     Ok(Arc::new(projection))
 }
 
 /// PhysicalExpr implementation for partition value calculation
+///
+/// The [`PartitionValueCalculator`] cannot be serialized, so the spec and 
schema it
+/// was built from are retained for [`Self::try_new`] to rebuild from.
 #[derive(Debug, Clone)]
-struct PartitionExpr {
+pub struct PartitionExpr {
     calculator: Arc<PartitionValueCalculator>,
     partition_spec: Arc<PartitionSpec>,
+    table_schema: IcebergSchemaRef,
 }
 
 impl PartitionExpr {
-    fn new(
-        calculator: PartitionValueCalculator,
+    /// Builds the expression from the spec and schema that define it.
+    ///
+    /// The calculator is built here rather than passed in, so it cannot drift 
from
+    /// the retained inputs.
+    ///
+    /// # Errors
+    ///
+    /// Returns an error if the spec is unpartitioned or cannot be bound to 
the schema.
+    pub fn try_new(

Review Comment:
   Since `PartitionExpr` is now part of the public API and a codec author will 
start from `try_new`, could it have a doc example that runs as a doctest? The 
rebuild round trip is the reason this type is public, so it makes a good 
example, and running it as a doctest means it can't go stale. I ran the example 
below on the head commit with `cargo test -p datafusion-iceberg --doc 
PartitionExpr` and it passes.
   
   ```suggestion
       /// Returns an error if the spec is unpartitioned or cannot be bound to 
the schema.
       ///
       /// # Example
       ///
       /// ```
       /// use std::sync::Arc;
       ///
       /// use datafusion_iceberg::physical_plan::PartitionExpr;
       /// use iceberg::spec::{NestedField, PartitionSpec, PrimitiveType, 
Schema, Transform, Type};
       ///
       /// let schema = Arc::new(
       ///     Schema::builder()
       ///         .with_fields(vec![
       ///             NestedField::required(1, "id", 
Type::Primitive(PrimitiveType::Int)).into(),
       ///         ])
       ///         .build()?,
       /// );
       /// let spec = Arc::new(
       ///     PartitionSpec::builder(schema.clone())
       ///         .add_partition_field("id", "id_bucket", 
Transform::Bucket(16))?
       ///         .build()?,
       /// );
       /// let expr = PartitionExpr::try_new(spec, schema)?;
       ///
       /// // A worker rebuilds an equal expression from the two retained 
inputs.
       /// let rebuilt = PartitionExpr::try_new(
       ///     Arc::new(expr.partition_spec().as_ref().clone()),
       ///     Arc::new(expr.table_schema().as_ref().clone()),
       /// )?;
       /// assert_eq!(expr, rebuilt);
       /// # Ok::<(), Box<dyn std::error::Error>>(())
       /// ```
   ```



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