kosiew commented on code in PR #23914:
URL: https://github.com/apache/datafusion/pull/23914#discussion_r3819533457


##########
datafusion/common/src/nested_struct.rs:
##########
@@ -1292,6 +1538,566 @@ mod tests {
         assert!(b_col.is_null(1));
     }
 
+    fn map_type(key_type: DataType, value_type: DataType) -> DataType {
+        map_type_with_entry_names(key_type, value_type, "keys", "values", 
false)
+    }
+
+    fn map_type_with_entry_names(
+        key_type: DataType,
+        value_type: DataType,
+        key_name: &str,
+        value_name: &str,
+        sorted: bool,
+    ) -> DataType {
+        DataType::Map(
+            Arc::new(non_null_field(
+                "entries",
+                struct_type(vec![
+                    non_null_field(key_name, key_type),
+                    field(value_name, value_type),
+                ]),
+            )),
+            sorted,
+        )
+    }
+
+    fn struct_map_array() -> ArrayRef {
+        struct_map_array_with_sorted(false)
+    }
+
+    fn struct_map_array_with_sorted(sorted: bool) -> ArrayRef {
+        struct_map_array_with_key_fields(sorted, false)
+    }
+
+    fn struct_map_array_with_key_fields(sorted: bool, include_tenant: bool) -> 
ArrayRef {
+        let mut key_fields = vec![(
+            arc_field("id", DataType::Int32),
+            Arc::new(Int32Array::from(vec![1])) as ArrayRef,
+        )];
+        if include_tenant {
+            key_fields.push((
+                arc_field("tenant", DataType::Utf8),
+                Arc::new(StringArray::from(vec!["a"])) as ArrayRef,
+            ));
+        }
+        let keys = StructArray::from(key_fields);
+        let values = StructArray::from(vec![
+            (
+                arc_field("amount", DataType::Int32),
+                Arc::new(Int32Array::from(vec![10])) as ArrayRef,
+            ),
+            (
+                arc_field("ignored", DataType::Utf8),
+                Arc::new(StringArray::from(vec!["x"])) as ArrayRef,
+            ),
+        ]);
+        let entries = StructArray::new(
+            vec![
+                Arc::new(non_null_field("keys", keys.data_type().clone())),
+                arc_field("values", values.data_type().clone()),
+            ]
+            .into(),
+            vec![Arc::new(keys), Arc::new(values)],
+            None,
+        );
+        Arc::new(MapArray::new(
+            Arc::new(non_null_field("entries", entries.data_type().clone())),
+            OffsetBuffer::new(vec![0, 1, 1].into()),
+            entries,
+            Some(NullBuffer::from(vec![true, false])),
+            sorted,
+        ))
+    }
+
+    fn nested_struct_map_array(
+        key_name: &str,
+        value_name: &str,
+        sorted: bool,
+    ) -> ArrayRef {
+        let key_nested = StructArray::from(vec![(
+            arc_field("id", DataType::Int32),
+            Arc::new(Int32Array::from(vec![1])) as ArrayRef,
+        )]);
+        let keys = StructArray::from(vec![(
+            arc_field("nested", key_nested.data_type().clone()),
+            Arc::new(key_nested) as ArrayRef,
+        )]);
+        let value_nested = StructArray::from(vec![(
+            arc_field("amount", DataType::Int32),
+            Arc::new(Int32Array::from(vec![10])) as ArrayRef,
+        )]);
+        let values = StructArray::from(vec![(
+            arc_field("nested", value_nested.data_type().clone()),
+            Arc::new(value_nested) as ArrayRef,
+        )]);
+        let entries = StructArray::new(
+            vec![
+                Arc::new(non_null_field(key_name, keys.data_type().clone())),
+                arc_field(value_name, values.data_type().clone()),
+            ]
+            .into(),
+            vec![Arc::new(keys), Arc::new(values)],
+            None,
+        );
+        Arc::new(MapArray::new(
+            Arc::new(non_null_field("entries", entries.data_type().clone())),
+            OffsetBuffer::new(vec![0, 1].into()),
+            entries,
+            None,
+            sorted,
+        ))
+    }
+
+    #[test]
+    fn test_map_entry_names_match_positionally_and_adapt_nested_structs() {
+        let source_col = nested_struct_map_array("source_keys", 
"source_values", false);
+        let target_type = map_type_with_entry_names(
+            struct_type(vec![field(
+                "nested",
+                struct_type(vec![
+                    field("id", DataType::Int64),
+                    field("label", DataType::Utf8),
+                ]),
+            )]),
+            struct_type(vec![field(
+                "nested",
+                struct_type(vec![
+                    field("amount", DataType::Int64),
+                    field("currency", DataType::Utf8),
+                ]),
+            )]),
+            "key",
+            "value",
+            false,
+        );
+
+        assert!(
+            validate_data_type_compatibility(
+                "map_col",
+                source_col.data_type(),
+                &target_type
+            )
+            .is_ok()
+        );
+        let result =
+            cast_column(&source_col, &target_type, 
&DEFAULT_CAST_OPTIONS).unwrap();
+        let map = result.as_any().downcast_ref::<MapArray>().unwrap();
+        let (key_field, value_field) = map.entries_fields();
+        assert_eq!(key_field.name(), "key");
+        assert_eq!(value_field.name(), "value");
+        let keys = map.keys().as_struct();
+        let key_nested = keys.column_by_name("nested").unwrap().as_struct();
+        assert_eq!(get_column_as!(key_nested, "id", Int64Array).value(0), 1);
+        assert!(get_column_as!(key_nested, "label", StringArray).is_null(0));
+        let values = map.values().as_struct();
+        let value_nested = 
values.column_by_name("nested").unwrap().as_struct();
+        assert_eq!(
+            get_column_as!(value_nested, "amount", Int64Array).value(0),
+            10
+        );
+        assert!(get_column_as!(value_nested, "currency", 
StringArray).is_null(0));
+    }
+
+    #[test]
+    fn 
test_unsorted_map_key_struct_field_removal_rejected_by_planner_and_runtime() {
+        let source_col = struct_map_array_with_key_fields(false, true);
+        let target_type = map_type(
+            struct_type(vec![field("id", DataType::Int32)]),
+            struct_type(vec![
+                field("amount", DataType::Int32),
+                field("ignored", DataType::Utf8),
+            ]),
+        );
+        assert_map_planning_runtime_error(
+            &source_col,
+            &target_type,
+            "Cannot remove field 'tenant' from a Map key Struct",
+        );
+    }
+
+    #[test]
+    fn test_unsorted_map_non_injective_key_cast_rejected() {

Review Comment:
   [added planner+runtime Map(Int32, Utf8) -> Map(Int64, Utf8) 
test](https://github.com/apache/datafusion/pull/23914/commits/f73a2ee1f9cec6f3754f8d7072ca623fcedbdfaa)
  



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