@@ -21,7 +21,7 @@ use crate::spec::{DataField, Datum, Predicate, PredicateOperator};
2121use crate :: table:: { ArrowRecordBatchStream , RowRange } ;
2222use crate :: Error ;
2323use arrow_array:: RecordBatch ;
24- use arrow_schema:: SchemaRef ;
24+ use arrow_schema:: { DataType as ArrowDataType , SchemaRef } ;
2525use async_trait:: async_trait;
2626use futures:: future:: BoxFuture ;
2727use futures:: StreamExt ;
@@ -472,7 +472,7 @@ fn vortex_array_to_record_batch(
472472 schema : & SchemaRef ,
473473) -> crate :: Result < RecordBatch > {
474474 let arrow_array = vortex_array
475- . into_arrow_preferred ( )
475+ . into_arrow ( & ArrowDataType :: Struct ( schema . fields ( ) . clone ( ) ) )
476476 . map_err ( |e| Error :: DataInvalid {
477477 message : format ! ( "Failed to convert Vortex array to Arrow: {e}" ) ,
478478 source : None ,
@@ -486,6 +486,17 @@ fn vortex_array_to_record_batch(
486486 source : None ,
487487 } ) ?;
488488
489+ if struct_array. columns ( ) . len ( ) != schema. fields ( ) . len ( ) {
490+ return Err ( Error :: DataInvalid {
491+ message : format ! (
492+ "Vortex column count {} does not match target schema column count {}" ,
493+ struct_array. columns( ) . len( ) ,
494+ schema. fields( ) . len( )
495+ ) ,
496+ source : None ,
497+ } ) ;
498+ }
499+
489500 RecordBatch :: try_new ( schema. clone ( ) , struct_array. columns ( ) . to_vec ( ) ) . map_err ( |e| {
490501 Error :: DataInvalid {
491502 message : format ! ( "Failed to build RecordBatch from Vortex data: {e}" ) ,
@@ -680,7 +691,8 @@ mod tests {
680691 use super :: * ;
681692 use crate :: arrow:: format:: FormatFileWriter ;
682693 use crate :: io:: FileIOBuilder ;
683- use arrow_array:: Int32Array ;
694+ use crate :: spec:: { DataField , DataType , VarCharType } ;
695+ use arrow_array:: { Int32Array , StringArray } ;
684696 use arrow_schema:: { DataType as ArrowDataType , Field as ArrowField , Schema as ArrowSchema } ;
685697
686698 fn test_arrow_schema ( ) -> Arc < ArrowSchema > {
@@ -758,6 +770,78 @@ mod tests {
758770 assert_eq ! ( total_rows, 3 ) ;
759771 }
760772
773+ #[ tokio:: test]
774+ async fn test_vortex_reader_returns_utf8_for_string_schema ( ) {
775+ let file_io = FileIOBuilder :: new ( "memory" ) . build ( ) . unwrap ( ) ;
776+ let path = "memory:/test_vortex_utf8_schema.vortex" ;
777+ let output = file_io. new_output ( path) . unwrap ( ) ;
778+ let schema = Arc :: new ( ArrowSchema :: new ( vec ! [
779+ ArrowField :: new( "id" , ArrowDataType :: Int32 , false ) ,
780+ ArrowField :: new( "name" , ArrowDataType :: Utf8 , true ) ,
781+ ] ) ) ;
782+
783+ let mut writer: Box < dyn FormatFileWriter > = Box :: new (
784+ VortexFormatWriter :: new ( & output, schema. clone ( ) )
785+ . await
786+ . unwrap ( ) ,
787+ ) ;
788+ let batch = RecordBatch :: try_new (
789+ schema,
790+ vec ! [
791+ Arc :: new( Int32Array :: from( vec![ 1 , 2 ] ) ) ,
792+ Arc :: new( StringArray :: from( vec![ Some ( "Alice" ) , Some ( "Bob" ) ] ) ) ,
793+ ] ,
794+ )
795+ . unwrap ( ) ;
796+ writer. write ( & batch) . await . unwrap ( ) ;
797+ writer. close ( ) . await . unwrap ( ) ;
798+
799+ let input = file_io. new_input ( path) . unwrap ( ) ;
800+ let file_reader = input. reader ( ) . await . unwrap ( ) ;
801+ let metadata = input. metadata ( ) . await . unwrap ( ) ;
802+ let read_fields = vec ! [
803+ DataField :: new(
804+ 0 ,
805+ "id" . to_string( ) ,
806+ DataType :: Int ( crate :: spec:: IntType :: new( ) ) ,
807+ ) ,
808+ DataField :: new(
809+ 1 ,
810+ "name" . to_string( ) ,
811+ DataType :: VarChar ( VarCharType :: string_type( ) ) ,
812+ ) ,
813+ ] ;
814+
815+ let reader = VortexFormatReader ;
816+ let mut stream = reader
817+ . read_batch_stream (
818+ Box :: new ( file_reader) ,
819+ metadata. size ,
820+ & read_fields,
821+ None ,
822+ None ,
823+ None ,
824+ )
825+ . await
826+ . unwrap ( ) ;
827+
828+ let mut names = Vec :: new ( ) ;
829+ while let Some ( result) = stream. next ( ) . await {
830+ let batch = result. unwrap ( ) ;
831+ assert_eq ! ( batch. schema( ) . field( 1 ) . data_type( ) , & ArrowDataType :: Utf8 ) ;
832+ assert_eq ! ( batch. column( 1 ) . data_type( ) , & ArrowDataType :: Utf8 ) ;
833+ let name_col = batch
834+ . column ( 1 )
835+ . as_any ( )
836+ . downcast_ref :: < StringArray > ( )
837+ . unwrap ( ) ;
838+ for i in 0 ..batch. num_rows ( ) {
839+ names. push ( name_col. value ( i) . to_string ( ) ) ;
840+ }
841+ }
842+ assert_eq ! ( names, vec![ "Alice" . to_string( ) , "Bob" . to_string( ) ] ) ;
843+ }
844+
761845 #[ tokio:: test]
762846 async fn test_vortex_writer_multiple_batches ( ) {
763847 let file_io = FileIOBuilder :: new ( "memory" ) . build ( ) . unwrap ( ) ;
0 commit comments