@@ -1716,6 +1716,7 @@ def _task_to_record_batches(
17161716 downcast_ns_timestamp_to_us = downcast_ns_timestamp_to_us ,
17171717 projected_missing_fields = projected_missing_fields ,
17181718 allow_timestamp_tz_mismatch = True ,
1719+ dictionary_columns = dictionary_columns ,
17191720 )
17201721
17211722
@@ -1910,6 +1911,7 @@ def _to_requested_schema(
19101911 projected_missing_fields : dict [int , Any ] = EMPTY_DICT ,
19111912 allow_timestamp_tz_mismatch : bool = False ,
19121913 format_model : FileFormatModel | None = None ,
1914+ dictionary_columns : tuple [str , ...] = (),
19131915) -> pa .RecordBatch :
19141916 # We could reuse some of these visitors
19151917 struct_array = visit_with_partner (
@@ -1922,6 +1924,7 @@ def _to_requested_schema(
19221924 projected_missing_fields = projected_missing_fields ,
19231925 allow_timestamp_tz_mismatch = allow_timestamp_tz_mismatch ,
19241926 format_model = format_model ,
1927+ dictionary_columns = dictionary_columns ,
19251928 ),
19261929 ArrowAccessor (file_schema ),
19271930 )
@@ -1935,6 +1938,7 @@ class ArrowProjectionVisitor(SchemaWithPartnerVisitor[pa.Array, pa.Array | None]
19351938 _projected_missing_fields : dict [int , Any ]
19361939 _allow_timestamp_tz_mismatch : bool
19371940 _format_model : FileFormatModel | None
1941+ _dictionary_columns : tuple [str , ...]
19381942
19391943 def __init__ (
19401944 self ,
@@ -1944,6 +1948,7 @@ def __init__(
19441948 projected_missing_fields : dict [int , Any ] = EMPTY_DICT ,
19451949 allow_timestamp_tz_mismatch : bool = False ,
19461950 format_model : FileFormatModel | None = None ,
1951+ dictionary_columns : tuple [str , ...] = (),
19471952 ) -> None :
19481953 if include_field_ids and format_model is None :
19491954 raise ValueError ("format_model is required when include_field_ids=True" )
@@ -1955,12 +1960,18 @@ def __init__(
19551960 # Allowed for reading (aligns with Spark); disallowed for writing to enforce Iceberg spec's strict typing.
19561961 self ._allow_timestamp_tz_mismatch = allow_timestamp_tz_mismatch
19571962 self ._format_model = format_model
1963+ self ._dictionary_columns = dictionary_columns
19581964
19591965 def _cast_if_needed (self , field : NestedField , values : pa .Array ) -> pa .Array :
19601966 file_field = self ._file_schema .find_field (field .field_id )
19611967
19621968 if field .field_type .is_primitive :
19631969 if (target_type := schema_to_pyarrow (field .field_type , include_field_ids = self ._include_field_ids )) != values .type :
1970+ if pa .types .is_dictionary (values .type ):
1971+ if field .name not in self ._dictionary_columns :
1972+ return values .cast (target_type )
1973+ return values
1974+
19641975 if field .field_type == TimestampType ():
19651976 source_tz_compatible = values .type .tz is None or (
19661977 self ._allow_timestamp_tz_mismatch and values .type .tz in UTC_ALIASES
0 commit comments