This is an automated email from the ASF dual-hosted git repository.

liurenjie1024 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 bdb8bf7c feat: support more partition transformations for 
PartitionSpec::partition_to_path (#1730)
bdb8bf7c is described below

commit bdb8bf7c6a55d30ae474b12535b22024144dea56
Author: Mrinal Paliwal <[email protected]>
AuthorDate: Sat Oct 11 09:13:31 2025 +0530

    feat: support more partition transformations for 
PartitionSpec::partition_to_path (#1730)
    
    ## Which issue does this PR close?
    
    
    
    - Closes #1729 .
    
    ## What changes are included in this PR?
    
    - Support more transformation types in `Transform::to_human_string`
    - Change visibility of few methods to pub
    
    ## Are these changes tested?
    
    
    Updated existing unit test
    
    Co-authored-by: Renjie Liu <[email protected]>
---
 crates/iceberg/src/spec/partition.rs | 20 +++++++++++++++++---
 crates/iceberg/src/spec/transform.rs | 24 +++++++++++-------------
 crates/iceberg/src/spec/values.rs    |  2 +-
 3 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/crates/iceberg/src/spec/partition.rs 
b/crates/iceberg/src/spec/partition.rs
index 128db338..b594895c 100644
--- a/crates/iceberg/src/spec/partition.rs
+++ b/crates/iceberg/src/spec/partition.rs
@@ -155,7 +155,9 @@ impl PartitionSpec {
         true
     }
 
-    pub(crate) fn partition_to_path(&self, data: &Struct, schema: SchemaRef) 
-> String {
+    /// Returns partition path string containing partition type and partition
+    /// value as key-value pairs.
+    pub fn partition_to_path(&self, data: &Struct, schema: SchemaRef) -> 
String {
         let partition_type = self.partition_type(&schema).unwrap();
         let field_types = partition_type.fields();
 
@@ -1813,6 +1815,9 @@ mod tests {
             .with_fields(vec![
                 NestedField::required(1, "id", 
Type::Primitive(PrimitiveType::Int)).into(),
                 NestedField::required(2, "name", 
Type::Primitive(PrimitiveType::String)).into(),
+                NestedField::required(3, "timestamp", 
Type::Primitive(PrimitiveType::Timestamp))
+                    .into(),
+                NestedField::required(4, "empty", 
Type::Primitive(PrimitiveType::String)).into(),
             ])
             .build()
             .unwrap();
@@ -1822,14 +1827,23 @@ mod tests {
             .unwrap()
             .add_partition_field("name", "name", Transform::Identity)
             .unwrap()
+            .add_partition_field("timestamp", "ts_hour", Transform::Hour)
+            .unwrap()
+            .add_partition_field("empty", "empty_void", Transform::Void)
+            .unwrap()
             .build()
             .unwrap();
 
-        let data = Struct::from_iter([Some(Literal::int(42)), 
Some(Literal::string("alice"))]);
+        let data = Struct::from_iter([
+            Some(Literal::int(42)),
+            Some(Literal::string("alice")),
+            Some(Literal::int(1000)),
+            Some(Literal::string("empty")),
+        ]);
 
         assert_eq!(
             spec.partition_to_path(&data, schema.into()),
-            "id=42/name=alice"
+            "id=42/name=alice/ts_hour=1000/empty_void=null"
         );
     }
 }
diff --git a/crates/iceberg/src/spec/transform.rs 
b/crates/iceberg/src/spec/transform.rs
index 8b6d2225..d69d15c2 100644
--- a/crates/iceberg/src/spec/transform.rs
+++ b/crates/iceberg/src/spec/transform.rs
@@ -137,19 +137,17 @@ pub enum Transform {
 impl Transform {
     /// Returns a human-readable String representation of a transformed value.
     pub fn to_human_string(&self, field_type: &Type, value: Option<&Literal>) 
-> String {
-        if let Some(value) = value {
-            if let Some(value) = value.as_primitive_literal() {
-                let field_type = field_type.as_primitive_type().unwrap();
-                let datum = Datum::new(field_type.clone(), value);
-                match self {
-                    Self::Identity => datum.to_human_string(),
-                    Self::Void => "null".to_string(),
-                    _ => {
-                        todo!()
-                    }
-                }
-            } else {
-                "null".to_string()
+        let Some(value) = value else {
+            return "null".to_string();
+        };
+
+        if let Some(value) = value.as_primitive_literal() {
+            let field_type = field_type.as_primitive_type().unwrap();
+            let datum = Datum::new(field_type.clone(), value);
+
+            match self {
+                Self::Void => "null".to_string(),
+                _ => datum.to_human_string(),
             }
         } else {
             "null".to_string()
diff --git a/crates/iceberg/src/spec/values.rs 
b/crates/iceberg/src/spec/values.rs
index 7f214810..8d56604b 100644
--- a/crates/iceberg/src/spec/values.rs
+++ b/crates/iceberg/src/spec/values.rs
@@ -1271,7 +1271,7 @@ impl Datum {
     ///
     /// For string literals, this returns the raw string value without quotes.
     /// For all other literals, it falls back to [`to_string()`].
-    pub(crate) fn to_human_string(&self) -> String {
+    pub fn to_human_string(&self) -> String {
         match self.literal() {
             PrimitiveLiteral::String(s) => s.to_string(),
             _ => self.to_string(),

Reply via email to