@@ -74,7 +74,7 @@ impl SchemaVisitor for SchemaToAvroSchema {
7474 record. name = Name :: from ( format ! ( "r{}" , field. id) . as_str ( ) ) ;
7575 }
7676
77- if !field. required {
77+ if !field. required && ! matches ! ( field_schema , AvroSchema :: Null ) {
7878 field_schema = avro_optional ( field_schema) ?;
7979 }
8080
@@ -126,7 +126,7 @@ impl SchemaVisitor for SchemaToAvroSchema {
126126 record. name = Name :: from ( format ! ( "r{}" , list. element_field. id) . as_str ( ) ) ;
127127 }
128128
129- if !list. element_field . required {
129+ if !list. element_field . required && ! matches ! ( field_schema , AvroSchema :: Null ) {
130130 field_schema = avro_optional ( field_schema) ?;
131131 }
132132
@@ -147,7 +147,7 @@ impl SchemaVisitor for SchemaToAvroSchema {
147147 ) -> Result < AvroSchemaOrField > {
148148 let key_field_schema = key_value. unwrap_left ( ) ;
149149 let mut value_field_schema = value. unwrap_left ( ) ;
150- if !map. value_field . required {
150+ if !map. value_field . required && ! matches ! ( value_field_schema , AvroSchema :: Null ) {
151151 value_field_schema = avro_optional ( value_field_schema) ?;
152152 }
153153
@@ -222,6 +222,7 @@ impl SchemaVisitor for SchemaToAvroSchema {
222222
223223 fn primitive ( & mut self , p : & PrimitiveType ) -> Result < AvroSchemaOrField > {
224224 let avro_schema = match p {
225+ PrimitiveType :: Unknown => AvroSchema :: Null ,
225226 PrimitiveType :: Boolean => AvroSchema :: Boolean ,
226227 PrimitiveType :: Int => AvroSchema :: Int ,
227228 PrimitiveType :: Long => AvroSchema :: Long ,
@@ -304,6 +305,10 @@ pub(crate) fn avro_decimal_schema(precision: usize, scale: usize) -> Result<Avro
304305}
305306
306307fn avro_optional ( avro_schema : AvroSchema ) -> Result < AvroSchema > {
308+ if matches ! ( avro_schema, AvroSchema :: Null ) {
309+ return Ok ( AvroSchema :: Null ) ;
310+ }
311+
307312 Ok ( AvroSchema :: Union ( UnionSchema :: new ( vec ! [
308313 AvroSchema :: Null ,
309314 avro_schema,
@@ -440,10 +445,11 @@ impl AvroSchemaVisitor for AvroSchemaToSchema {
440445 let field_id =
441446 Self :: get_element_id_from_attributes ( & avro_field. custom_attributes , FIELD_ID_PROP ) ?;
442447
443- let optional = is_avro_optional ( & avro_field. schema ) ;
448+ let optional = is_avro_optional ( & avro_field. schema )
449+ || matches ! ( & avro_field. schema, AvroSchema :: Null ) ;
444450
445- let mut field =
446- NestedField :: new ( field_id, & avro_field. name , field_type. unwrap ( ) , !optional) ;
451+ let field_type = field_type . unwrap_or ( Type :: Primitive ( PrimitiveType :: Unknown ) ) ;
452+ let mut field = NestedField :: new ( field_id, & avro_field. name , field_type, !optional) ;
447453
448454 if let Some ( doc) = & avro_field. doc {
449455 field = field. with_doc ( doc) ;
@@ -475,18 +481,21 @@ impl AvroSchemaVisitor for AvroSchemaToSchema {
475481 }
476482
477483 if options. len ( ) == 1 {
478- Ok ( Some ( options. remove ( 0 ) . unwrap ( ) ) )
484+ Ok ( options
485+ . remove ( 0 )
486+ . or ( Some ( Type :: Primitive ( PrimitiveType :: Unknown ) ) ) )
479487 } else {
480488 Ok ( Some ( options. remove ( 1 ) . unwrap ( ) ) )
481489 }
482490 }
483491
484492 fn array ( & mut self , array : & ArraySchema , item : Option < Type > ) -> Result < Self :: T > {
485493 let element_field_id = Self :: get_element_id_from_attributes ( & array. attributes , ELEMENT_ID ) ?;
494+ let item = item. unwrap_or ( Type :: Primitive ( PrimitiveType :: Unknown ) ) ;
486495 let element_field = NestedField :: list_element (
487496 element_field_id,
488- item. unwrap ( ) ,
489- !is_avro_optional ( & array. items ) ,
497+ item,
498+ !is_avro_optional ( & array. items ) && ! matches ! ( array . items . as_ref ( ) , AvroSchema :: Null ) ,
490499 )
491500 . into ( ) ;
492501 Ok ( Some ( Type :: List ( ListType { element_field } ) ) )
@@ -497,10 +506,11 @@ impl AvroSchemaVisitor for AvroSchemaToSchema {
497506 let key_field =
498507 NestedField :: map_key_element ( key_field_id, Type :: Primitive ( PrimitiveType :: String ) ) ;
499508 let value_field_id = Self :: get_element_id_from_attributes ( & map. attributes , VALUE_ID ) ?;
509+ let value = value. unwrap_or ( Type :: Primitive ( PrimitiveType :: Unknown ) ) ;
500510 let value_field = NestedField :: map_value_element (
501511 value_field_id,
502- value. unwrap ( ) ,
503- !is_avro_optional ( & map. types ) ,
512+ value,
513+ !is_avro_optional ( & map. types ) && ! matches ! ( map . types . as_ref ( ) , AvroSchema :: Null ) ,
504514 ) ;
505515 Ok ( Some ( Type :: Map ( MapType {
506516 key_field : key_field. into ( ) ,
@@ -550,12 +560,7 @@ impl AvroSchemaVisitor for AvroSchemaToSchema {
550560 "Can't convert avro map schema, missing key schema." ,
551561 )
552562 } ) ?;
553- let value = value. ok_or_else ( || {
554- Error :: new (
555- ErrorKind :: DataInvalid ,
556- "Can't convert avro map schema, missing value schema." ,
557- )
558- } ) ?;
563+ let value = value. unwrap_or ( Type :: Primitive ( PrimitiveType :: Unknown ) ) ;
559564 let key_id = Self :: get_element_id_from_attributes (
560565 & array. fields [ 0 ] . custom_attributes ,
561566 FIELD_ID_PROP ,
@@ -568,7 +573,8 @@ impl AvroSchemaVisitor for AvroSchemaToSchema {
568573 let value_field = NestedField :: map_value_element (
569574 value_id,
570575 value,
571- !is_avro_optional ( & array. fields [ 1 ] . schema ) ,
576+ !is_avro_optional ( & array. fields [ 1 ] . schema )
577+ && !matches ! ( & array. fields[ 1 ] . schema, AvroSchema :: Null ) ,
572578 ) ;
573579 Ok ( Some ( Type :: Map ( MapType {
574580 key_field : key_field. into ( ) ,
@@ -650,6 +656,25 @@ mod tests {
650656 assert_eq ! ( iceberg_schema, converted_avro_converted_iceberg_schema) ;
651657 }
652658
659+ #[ test]
660+ fn test_unknown_type_schema_conversion ( ) {
661+ let schema = Schema :: builder ( )
662+ . with_fields ( vec ! [
663+ NestedField :: optional( 1 , "empty" , PrimitiveType :: Unknown . into( ) ) . into( ) ,
664+ ] )
665+ . build ( )
666+ . unwrap ( ) ;
667+
668+ let avro_schema = schema_to_avro_schema ( "table" , & schema) . unwrap ( ) ;
669+ let AvroSchema :: Record ( record) = & avro_schema else {
670+ panic ! ( "expected avro record schema" ) ;
671+ } ;
672+ assert ! ( matches!( record. fields[ 0 ] . schema, AvroSchema :: Null ) ) ;
673+ assert_eq ! ( record. fields[ 0 ] . default , Some ( Value :: Null ) ) ;
674+
675+ assert_eq ! ( schema, avro_schema_to_schema( & avro_schema) . unwrap( ) ) ;
676+ }
677+
653678 #[ test]
654679 fn test_manifest_file_v1_schema ( ) {
655680 let fields = vec ! [
0 commit comments