1616// under the License.
1717
1818use arrow:: array:: {
19- Array , ArrayRef , BooleanArray , Int16Array , Int32Array , Int64Array , Int8Array , LargeStringArray ,
20- StringArray , StringBuilder ,
19+ as_boolean_array, as_largestring_array, as_string_array, Array , ArrayRef , StringBuilder ,
2120} ;
2221use arrow:: array:: { RecordBatch , StructArray } ;
2322use arrow:: datatypes:: { DataType , Schema } ;
23+ use datafusion:: common:: cast:: { as_int16_array, as_int32_array, as_int64_array, as_int8_array} ;
2424use datafusion:: common:: { exec_err, Result } ;
2525use datafusion:: logical_expr:: ColumnarValue ;
2626use datafusion:: physical_expr:: PhysicalExpr ;
@@ -96,6 +96,10 @@ impl PhysicalExpr for ToCsv {
9696 Ok ( DataType :: Utf8 )
9797 }
9898
99+ fn nullable ( & self , input_schema : & Schema ) -> Result < bool > {
100+ self . expr . nullable ( input_schema)
101+ }
102+
99103 fn evaluate ( & self , batch : & RecordBatch ) -> Result < ColumnarValue > {
100104 let input_value = self . expr . evaluate ( batch) ?. into_array ( batch. num_rows ( ) ) ?;
101105
@@ -134,6 +138,7 @@ impl PhysicalExpr for ToCsv {
134138fn struct_to_csv ( array : & StructArray , delimiter : & str , null_value : & str ) -> Result < ArrayRef > {
135139 let mut builder = StringBuilder :: with_capacity ( array. len ( ) , array. len ( ) * 16 ) ;
136140 let mut csv_string = String :: with_capacity ( array. len ( ) * 16 ) ;
141+
137142 for row_idx in 0 ..array. len ( ) {
138143 if array. is_null ( row_idx) {
139144 builder. append_null ( ) ;
@@ -146,8 +151,7 @@ fn struct_to_csv(array: &StructArray, delimiter: &str, null_value: &str) -> Resu
146151 if column. is_null ( row_idx) {
147152 csv_string. push_str ( null_value) ;
148153 } else {
149- let value = convert_to_string ( column, row_idx) ?;
150- csv_string. push_str ( & value) ;
154+ convert_to_string ( column, & mut csv_string, row_idx) ?;
151155 }
152156 }
153157 }
@@ -156,38 +160,40 @@ fn struct_to_csv(array: &StructArray, delimiter: &str, null_value: &str) -> Resu
156160 Ok ( Arc :: new ( builder. finish ( ) ) )
157161}
158162
159- fn convert_to_string ( array : & ArrayRef , row_idx : usize ) -> Result < String > {
163+ #[ inline]
164+ fn convert_to_string ( array : & ArrayRef , csv_string : & mut String , row_idx : usize ) -> Result < ( ) > {
160165 match array. data_type ( ) {
161166 DataType :: Boolean => {
162- let array = array . as_any ( ) . downcast_ref :: < BooleanArray > ( ) . unwrap ( ) ;
163- Ok ( array. value ( row_idx) . to_string ( ) )
167+ let array = as_boolean_array ( array ) ;
168+ csv_string . push_str ( & array. value ( row_idx) . to_string ( ) )
164169 }
165170 DataType :: Int8 => {
166- let array = array . as_any ( ) . downcast_ref :: < Int8Array > ( ) . unwrap ( ) ;
167- Ok ( array. value ( row_idx) . to_string ( ) )
171+ let array = as_int8_array ( array ) ? ;
172+ csv_string . push_str ( & array. value ( row_idx) . to_string ( ) )
168173 }
169174 DataType :: Int16 => {
170- let array = array . as_any ( ) . downcast_ref :: < Int16Array > ( ) . unwrap ( ) ;
171- Ok ( array. value ( row_idx) . to_string ( ) )
175+ let array = as_int16_array ( array ) ? ;
176+ csv_string . push_str ( & array. value ( row_idx) . to_string ( ) )
172177 }
173178 DataType :: Int32 => {
174- let array = array . as_any ( ) . downcast_ref :: < Int32Array > ( ) . unwrap ( ) ;
175- Ok ( array. value ( row_idx) . to_string ( ) )
179+ let array = as_int32_array ( array ) ? ;
180+ csv_string . push_str ( & array. value ( row_idx) . to_string ( ) )
176181 }
177182 DataType :: Int64 => {
178- let array = array . as_any ( ) . downcast_ref :: < Int64Array > ( ) . unwrap ( ) ;
179- Ok ( array. value ( row_idx) . to_string ( ) )
183+ let array = as_int64_array ( array ) ? ;
184+ csv_string . push_str ( & array. value ( row_idx) . to_string ( ) )
180185 }
181186 DataType :: Utf8 => {
182- let array = array . as_any ( ) . downcast_ref :: < StringArray > ( ) . unwrap ( ) ;
183- Ok ( array. value ( row_idx) . to_string ( ) )
187+ let array = as_string_array ( array ) ;
188+ csv_string . push_str ( & array. value ( row_idx) . to_string ( ) )
184189 }
185190 DataType :: LargeUtf8 => {
186- let array = array . as_any ( ) . downcast_ref :: < LargeStringArray > ( ) . unwrap ( ) ;
187- Ok ( array. value ( row_idx) . to_string ( ) )
191+ let array = as_largestring_array ( array ) ;
192+ csv_string . push_str ( & array. value ( row_idx) . to_string ( ) )
188193 }
189- _ => exec_err ! ( "to_csv not implemented for type: {:?}" , array. data_type( ) ) ,
194+ _ => return exec_err ! ( "to_csv not implemented for type: {:?}" , array. data_type( ) ) ,
190195 }
196+ Ok ( ( ) )
191197}
192198
193199#[ cfg( test) ]
0 commit comments