@@ -390,13 +390,11 @@ fn struct_columns_from_patch(
390390/// types come from `output_type`, which must be a struct holding only primitive fields (matching
391391/// the kernel evaluator, which supports only primitive targets).
392392///
393- /// Each field extracts its value with `cast(get_field(map, name), T)`. For a numeric or temporal
394- /// type the raw value is first wrapped in `nullif(.., '')`, mapping an empty string to null before
395- /// the cast, so an empty string becomes null (kernel's `empty_string_partition_cast`) while an
396- /// unparseable value fails the cast (kernel's hard parse error). String and Binary keep the raw
397- /// value (empty is a valid empty string / empty bytes). A missing key or null value is already null
398- /// via [`get_field`]. The whole struct is nulled where the input map row is null, via `<map> IS NOT
399- /// NULL`.
393+ /// Each field extracts its value with `cast(get_field(map, name), T)`. For every type except String
394+ /// and Binary, the raw value is first wrapped in `nullif(.., '')`, mapping an empty string to null
395+ /// before the cast. String and Binary keep the raw value because empty strings and bytes are valid.
396+ /// A missing key or null value is already null via [`get_field`]. The whole struct is nulled where
397+ /// the input map row is null, via `<map> IS NOT NULL`.
400398///
401399/// KNOWN DIVERGENCES from the kernel parser, confined to malformed or non-spec-compliant values
402400/// (spec-compliant writers never emit them):
@@ -408,14 +406,20 @@ fn struct_columns_from_patch(
408406/// value's scale to match the target's exactly (and hard-errors otherwise).
409407///
410408/// # Errors
411- /// Returns an error when `output_type` is absent, not a struct, or has a non-primitive field, or
412- /// from lowering the map expression.
409+ ///
410+ /// Returns an error when options are configured, `output_type` is absent, not a struct, or has a
411+ /// non-primitive field, or from lowering the map expression.
413412fn map_to_struct_to_df_expr (
414413 map_to_struct : & MapToStructExpression ,
415414 input_schema : & StructType ,
416415 output_type : Option < & KernelDataType > ,
417416) -> DeltaResult < DFExpr > {
418417 let target = require_struct_output ( output_type, "MapToStruct" ) ?;
418+ if !map_to_struct. options . is_default ( ) {
419+ return Err ( Error :: unsupported (
420+ "DataFusion execution of MapToStruct with configured options" ,
421+ ) ) ;
422+ }
419423 let map = to_df_expr ( & map_to_struct. map_expr , input_schema, None ) ?;
420424
421425 let mut args = Vec :: with_capacity ( target. num_fields ( ) * 2 ) ;
@@ -547,7 +551,7 @@ mod tests {
547551 use datafusion:: physical_expr:: execution_props:: ExecutionProps ;
548552 use delta_kernel:: expressions:: {
549553 col, lit, null_lit, ColumnName as KernelColumnName , Expression as KernelExpr ,
550- ExpressionStructPatch , ExpressionStructPatchBuilder ,
554+ ExpressionStructPatch , ExpressionStructPatchBuilder , MapToStructOptions ,
551555 } ;
552556 use delta_kernel:: schema:: { schema, schema_ref, ArrayType , DataType , MapType , StructType } ;
553557 use rstest:: rstest;
@@ -1001,7 +1005,7 @@ mod tests {
10011005 /// Lowers a `MapToStruct` over `pv` targeting `output_schema` and renders it as a `Display`
10021006 /// string.
10031007 fn lower_map_to_struct ( output_schema : StructType ) -> String {
1004- let kernel = KernelExpr :: map_to_struct ( col ! ( "pv" ) ) ;
1008+ let kernel = KernelExpr :: map_to_struct ( col ! ( "pv" ) , MapToStructOptions :: default ( ) ) ;
10051009 let target: DataType = output_schema. into ( ) ;
10061010 to_df_expr ( & kernel, & pv_map_schema ( ) , Some ( & target) )
10071011 . unwrap ( )
@@ -1063,13 +1067,28 @@ mod tests {
10631067 #[ case] output_type : Option < DataType > ,
10641068 #[ case] expected_message : & str ,
10651069 ) {
1066- let kernel = KernelExpr :: map_to_struct ( col ! ( "pv" ) ) ;
1070+ let kernel = KernelExpr :: map_to_struct ( col ! ( "pv" ) , MapToStructOptions :: default ( ) ) ;
10671071 let err = to_df_expr ( & kernel, & pv_map_schema ( ) , output_type. as_ref ( ) )
10681072 . unwrap_err ( )
10691073 . to_string ( ) ;
10701074 assert ! ( err. contains( expected_message) , "{err}" ) ;
10711075 }
10721076
1077+ #[ test]
1078+ fn configured_map_to_struct_is_unsupported ( ) {
1079+ let target = DataType :: from ( schema ! { nullable "ts" : TIMESTAMP } ) ;
1080+ let kernel = KernelExpr :: map_to_struct (
1081+ col ! ( "pv" ) ,
1082+ MapToStructOptions :: default ( ) . with_timestamp_timezone ( "America/Los_Angeles" ) ,
1083+ ) ;
1084+
1085+ let error = to_df_expr ( & kernel, & pv_map_schema ( ) , Some ( & target) )
1086+ . unwrap_err ( )
1087+ . to_string ( ) ;
1088+
1089+ assert ! ( error. contains( "MapToStruct with configured options" ) ) ;
1090+ }
1091+
10731092 // === ParseJson Shared Helpers ===
10741093
10751094 /// Input schema for JSON tests: `{ j: string }`.
0 commit comments