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

mbrobbel pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git


The following commit(s) were added to refs/heads/main by this push:
     new 4545c1ea2e feat: Ensure consistent metadata display for data types 
(#8760)
4545c1ea2e is described below

commit 4545c1ea2e5f4853617899d21968c2a8aae3706a
Author: Martin Hilton <[email protected]>
AuthorDate: Mon Nov 3 09:58:39 2025 +0000

    feat: Ensure consistent metadata display for data types (#8760)
    
    Where a datatype has associated metadata format that metadata
    consistently in lexical order by key.
    
    # Which issue does this PR close?
    
    - closes https://github.com/apache/arrow-rs/issues/8761
    - helps with #8351.
    
    # Rationale for this change
    
    
    # What changes are included in this PR?
    
    A consistent formatter for the metadata hash tables embedded in
    DataType.
    
    # Are these changes tested?
    
    Yes, I have enhanced an existing test that would have shown the issue.
    
    # Are there any user-facing changes?
    
    
    No
    
    ---------
    
    Co-authored-by: Andrew Lamb <[email protected]>
---
 arrow-schema/src/datatype_display.rs | 31 +++++++++++++++++++++++--------
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/arrow-schema/src/datatype_display.rs 
b/arrow-schema/src/datatype_display.rs
index 2d54e76dd8..6c89e3cdae 100644
--- a/arrow-schema/src/datatype_display.rs
+++ b/arrow-schema/src/datatype_display.rs
@@ -22,11 +22,7 @@ use crate::DataType;
 impl fmt::Display for DataType {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fn format_metadata(metadata: &HashMap<String, String>) -> String {
-            if metadata.is_empty() {
-                String::new()
-            } else {
-                format!(", metadata: {metadata:?}")
-            }
+            format!("{}", FormatMetadata(metadata))
         }
 
         fn format_field(field: &crate::Field) -> String {
@@ -182,6 +178,23 @@ impl fmt::Display for DataType {
     }
 }
 
+/// Adapter to format a metadata HashMap consistently.
+struct FormatMetadata<'a>(&'a HashMap<String, String>);
+
+impl fmt::Display for FormatMetadata<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let metadata = self.0;
+        if metadata.is_empty() {
+            Ok(())
+        } else {
+            let mut entries: Vec<(&String, &String)> = 
metadata.iter().collect();
+            entries.sort_by(|a, b| a.0.cmp(b.0));
+            write!(f, ", metadata: ")?;
+            f.debug_map().entries(entries).finish()
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
 
@@ -361,14 +374,16 @@ mod tests {
 
         // Test with metadata
         let mut field_with_metadata = Field::new("b", DataType::Utf8, true);
-        let metadata = HashMap::from([("key".to_string(), 
"value".to_string())]);
+        let metadata = HashMap::from([
+            ("key".to_string(), "value".to_string()),
+            ("key2".to_string(), "value2".to_string()),
+        ]);
         field_with_metadata.set_metadata(metadata);
         let struct_fields_with_metadata =
             vec![Field::new("a", DataType::Int32, false), field_with_metadata];
         let struct_data_type_with_metadata = 
DataType::Struct(struct_fields_with_metadata.into());
         let struct_data_type_with_metadata_string = 
struct_data_type_with_metadata.to_string();
-        let expected_string_with_metadata =
-            "Struct(\"a\": Int32, \"b\": nullable Utf8, metadata: {\"key\": 
\"value\"})";
+        let expected_string_with_metadata = "Struct(\"a\": Int32, \"b\": 
nullable Utf8, metadata: {\"key\": \"value\", \"key2\": \"value2\"})";
         assert_eq!(
             struct_data_type_with_metadata_string,
             expected_string_with_metadata

Reply via email to