@@ -2,6 +2,7 @@ use super::{
2
2
vector:: { FlatVector , ListVector , Vector } ,
3
3
BindInfo , DataChunk , Free , FunctionInfo , InitInfo , LogicalType , LogicalTypeId , StructVector , VTab ,
4
4
} ;
5
+ use std:: ptr:: null_mut;
5
6
6
7
use crate :: vtab:: vector:: Inserter ;
7
8
use arrow:: array:: {
@@ -74,8 +75,11 @@ impl VTab for ArrowVTab {
74
75
type InitData = ArrowInitData ;
75
76
76
77
unsafe fn bind ( bind : & BindInfo , data : * mut ArrowBindData ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
78
+ ( * data) . rb = null_mut ( ) ;
77
79
let param_count = bind. get_parameter_count ( ) ;
78
- assert ! ( param_count == 2 ) ;
80
+ if param_count != 2 {
81
+ return Err ( format ! ( "Bad param count: {param_count}, expected 2" ) . into ( ) ) ;
82
+ }
79
83
let array = bind. get_parameter ( 0 ) . to_int64 ( ) ;
80
84
let schema = bind. get_parameter ( 1 ) . to_int64 ( ) ;
81
85
unsafe {
@@ -106,6 +110,7 @@ impl VTab for ArrowVTab {
106
110
output. set_len ( 0 ) ;
107
111
} else {
108
112
let rb = Box :: from_raw ( ( * bind_info) . rb ) ;
113
+ ( * bind_info) . rb = null_mut ( ) ; // erase ref in case of failure in record_batch_to_duckdb_data_chunk
109
114
record_batch_to_duckdb_data_chunk ( & rb, output) ?;
110
115
( * bind_info) . rb = Box :: into_raw ( rb) ;
111
116
( * init_info) . done = true ;
@@ -156,7 +161,7 @@ pub fn to_duckdb_type_id(data_type: &DataType) -> Result<LogicalTypeId, Box<dyn
156
161
DataType :: List ( _) | DataType :: LargeList ( _) | DataType :: FixedSizeList ( _, _) => List ,
157
162
DataType :: Struct ( _) => Struct ,
158
163
DataType :: Union ( _, _) => Union ,
159
- DataType :: Dictionary ( _, _) => todo ! ( ) ,
164
+ // DataType::Dictionary(_, _) => todo!(),
160
165
// duckdb/src/main/capi/helper-c.cpp does not support decimal
161
166
// DataType::Decimal128(_, _) => Decimal,
162
167
// DataType::Decimal256(_, _) => Decimal,
@@ -194,8 +199,9 @@ pub fn to_duckdb_logical_type(data_type: &DataType) -> Result<LogicalType, Box<d
194
199
} else if let DataType :: FixedSizeList ( child, _) = data_type {
195
200
Ok ( LogicalType :: list ( & to_duckdb_logical_type ( child. data_type ( ) ) ?) )
196
201
} else {
197
- unimplemented ! (
198
- "Unsupported data type: {data_type}, please file an issue https://github.com/wangfenjin/duckdb-rs"
202
+ Err (
203
+ format ! ( "Unsupported data type: {data_type}, please file an issue https://github.com/wangfenjin/duckdb-rs" )
204
+ . into ( ) ,
199
205
)
200
206
}
201
207
}
@@ -216,30 +222,31 @@ pub fn record_batch_to_duckdb_data_chunk(
216
222
let col = batch. column ( i) ;
217
223
match col. data_type ( ) {
218
224
dt if dt. is_primitive ( ) || matches ! ( dt, DataType :: Boolean ) => {
219
- primitive_array_to_vector ( col, & mut chunk. flat_vector ( i) ) ;
225
+ primitive_array_to_vector ( col, & mut chunk. flat_vector ( i) ) ? ;
220
226
}
221
227
DataType :: Utf8 => {
222
228
string_array_to_vector ( as_string_array ( col. as_ref ( ) ) , & mut chunk. flat_vector ( i) ) ;
223
229
}
224
230
DataType :: List ( _) => {
225
- list_array_to_vector ( as_list_array ( col. as_ref ( ) ) , & mut chunk. list_vector ( i) ) ;
231
+ list_array_to_vector ( as_list_array ( col. as_ref ( ) ) , & mut chunk. list_vector ( i) ) ? ;
226
232
}
227
233
DataType :: LargeList ( _) => {
228
- list_array_to_vector ( as_large_list_array ( col. as_ref ( ) ) , & mut chunk. list_vector ( i) ) ;
234
+ list_array_to_vector ( as_large_list_array ( col. as_ref ( ) ) , & mut chunk. list_vector ( i) ) ? ;
229
235
}
230
236
DataType :: FixedSizeList ( _, _) => {
231
- fixed_size_list_array_to_vector ( as_fixed_size_list_array ( col. as_ref ( ) ) , & mut chunk. list_vector ( i) ) ;
237
+ fixed_size_list_array_to_vector ( as_fixed_size_list_array ( col. as_ref ( ) ) , & mut chunk. list_vector ( i) ) ? ;
232
238
}
233
239
DataType :: Struct ( _) => {
234
240
let struct_array = as_struct_array ( col. as_ref ( ) ) ;
235
241
let mut struct_vector = chunk. struct_vector ( i) ;
236
- struct_array_to_vector ( struct_array, & mut struct_vector) ;
242
+ struct_array_to_vector ( struct_array, & mut struct_vector) ? ;
237
243
}
238
244
_ => {
239
- unimplemented ! (
245
+ return Err ( format ! (
240
246
"column {} is not supported yet, please file an issue https://github.com/wangfenjin/duckdb-rs" ,
241
247
batch. schema( ) . field( i)
242
- ) ;
248
+ )
249
+ . into ( ) ) ;
243
250
}
244
251
}
245
252
}
@@ -262,7 +269,7 @@ fn primitive_array_to_flat_vector_cast<T: ArrowPrimitiveType>(
262
269
out_vector. copy :: < T :: Native > ( array. as_primitive :: < T > ( ) . values ( ) ) ;
263
270
}
264
271
265
- fn primitive_array_to_vector ( array : & dyn Array , out : & mut dyn Vector ) {
272
+ fn primitive_array_to_vector ( array : & dyn Array , out : & mut dyn Vector ) -> Result < ( ) , Box < dyn std :: error :: Error > > {
266
273
match array. data_type ( ) {
267
274
DataType :: Boolean => {
268
275
boolean_array_to_vector ( as_boolean_array ( array) , out. as_mut_any ( ) . downcast_mut ( ) . unwrap ( ) ) ;
@@ -315,7 +322,6 @@ fn primitive_array_to_vector(array: &dyn Array, out: &mut dyn Vector) {
315
322
out. as_mut_any ( ) . downcast_mut ( ) . unwrap ( ) ,
316
323
) ;
317
324
}
318
- DataType :: Float16 => todo ! ( "Float16 is not supported yet" ) ,
319
325
DataType :: Float32 => {
320
326
primitive_array_to_flat_vector :: < Float32Type > (
321
327
as_primitive_array ( array) ,
@@ -337,7 +343,6 @@ fn primitive_array_to_vector(array: &dyn Array, out: &mut dyn Vector) {
337
343
out. as_mut_any ( ) . downcast_mut ( ) . unwrap ( ) ,
338
344
) ;
339
345
}
340
- DataType :: Decimal256 ( _, _) => todo ! ( "Decimal256 is not supported yet" ) ,
341
346
342
347
// DuckDB Only supports timetamp_tz in microsecond precision
343
348
DataType :: Timestamp ( _, Some ( tz) ) => primitive_array_to_flat_vector_cast :: < TimestampMicrosecondType > (
@@ -376,11 +381,9 @@ fn primitive_array_to_vector(array: &dyn Array, out: &mut dyn Vector) {
376
381
DataType :: Time64 ( _) => {
377
382
primitive_array_to_flat_vector_cast :: < Time64MicrosecondType > ( Time64MicrosecondType :: DATA_TYPE , array, out)
378
383
}
379
- _ => todo ! (
380
- "Converting '{dtype:#?}' to primitive flat vector is not supported" ,
381
- dtype = array. data_type( )
382
- ) ,
384
+ datatype => return Err ( format ! ( "Data type \" {datatype}\" not yet supported by ArrowVTab" ) . into ( ) ) ,
383
385
}
386
+ Ok ( ( ) )
384
387
}
385
388
386
389
/// Convert Arrow [Decimal128Array] to a duckdb vector.
@@ -410,31 +413,38 @@ fn string_array_to_vector(array: &StringArray, out: &mut FlatVector) {
410
413
}
411
414
}
412
415
413
- fn list_array_to_vector < O : OffsetSizeTrait + AsPrimitive < usize > > ( array : & GenericListArray < O > , out : & mut ListVector ) {
416
+ fn list_array_to_vector < O : OffsetSizeTrait + AsPrimitive < usize > > (
417
+ array : & GenericListArray < O > ,
418
+ out : & mut ListVector ,
419
+ ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
414
420
let value_array = array. values ( ) ;
415
421
let mut child = out. child ( value_array. len ( ) ) ;
416
422
match value_array. data_type ( ) {
417
423
dt if dt. is_primitive ( ) => {
418
- primitive_array_to_vector ( value_array. as_ref ( ) , & mut child) ;
424
+ primitive_array_to_vector ( value_array. as_ref ( ) , & mut child) ? ;
419
425
for i in 0 ..array. len ( ) {
420
426
let offset = array. value_offsets ( ) [ i] ;
421
427
let length = array. value_length ( i) ;
422
428
out. set_entry ( i, offset. as_ ( ) , length. as_ ( ) ) ;
423
429
}
424
430
}
425
431
_ => {
426
- println ! ( "Nested list is not supported yet." ) ;
427
- todo ! ( )
432
+ return Err ( "Nested list is not supported yet." . into ( ) ) ;
428
433
}
429
434
}
435
+
436
+ Ok ( ( ) )
430
437
}
431
438
432
- fn fixed_size_list_array_to_vector ( array : & FixedSizeListArray , out : & mut ListVector ) {
439
+ fn fixed_size_list_array_to_vector (
440
+ array : & FixedSizeListArray ,
441
+ out : & mut ListVector ,
442
+ ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
433
443
let value_array = array. values ( ) ;
434
444
let mut child = out. child ( value_array. len ( ) ) ;
435
445
match value_array. data_type ( ) {
436
446
dt if dt. is_primitive ( ) => {
437
- primitive_array_to_vector ( value_array. as_ref ( ) , & mut child) ;
447
+ primitive_array_to_vector ( value_array. as_ref ( ) , & mut child) ? ;
438
448
for i in 0 ..array. len ( ) {
439
449
let offset = array. value_offset ( i) ;
440
450
let length = array. value_length ( ) ;
@@ -443,10 +453,11 @@ fn fixed_size_list_array_to_vector(array: &FixedSizeListArray, out: &mut ListVec
443
453
out. set_len ( value_array. len ( ) ) ;
444
454
}
445
455
_ => {
446
- println ! ( "Nested list is not supported yet." ) ;
447
- todo ! ( )
456
+ return Err ( "Nested list is not supported yet." . into ( ) ) ;
448
457
}
449
458
}
459
+
460
+ Ok ( ( ) )
450
461
}
451
462
452
463
/// Force downcast of an [`Array`], such as an [`ArrayRef`], to
@@ -455,32 +466,32 @@ fn as_fixed_size_list_array(arr: &dyn Array) -> &FixedSizeListArray {
455
466
arr. as_any ( ) . downcast_ref :: < FixedSizeListArray > ( ) . unwrap ( )
456
467
}
457
468
458
- fn struct_array_to_vector ( array : & StructArray , out : & mut StructVector ) {
469
+ fn struct_array_to_vector ( array : & StructArray , out : & mut StructVector ) -> Result < ( ) , Box < dyn std :: error :: Error > > {
459
470
for i in 0 ..array. num_columns ( ) {
460
471
let column = array. column ( i) ;
461
472
match column. data_type ( ) {
462
473
dt if dt. is_primitive ( ) || matches ! ( dt, DataType :: Boolean ) => {
463
- primitive_array_to_vector ( column, & mut out. child ( i) ) ;
474
+ primitive_array_to_vector ( column, & mut out. child ( i) ) ? ;
464
475
}
465
476
DataType :: Utf8 => {
466
477
string_array_to_vector ( as_string_array ( column. as_ref ( ) ) , & mut out. child ( i) ) ;
467
478
}
468
479
DataType :: List ( _) => {
469
- list_array_to_vector ( as_list_array ( column. as_ref ( ) ) , & mut out. list_vector_child ( i) ) ;
480
+ list_array_to_vector ( as_list_array ( column. as_ref ( ) ) , & mut out. list_vector_child ( i) ) ? ;
470
481
}
471
482
DataType :: LargeList ( _) => {
472
- list_array_to_vector ( as_large_list_array ( column. as_ref ( ) ) , & mut out. list_vector_child ( i) ) ;
483
+ list_array_to_vector ( as_large_list_array ( column. as_ref ( ) ) , & mut out. list_vector_child ( i) ) ? ;
473
484
}
474
485
DataType :: FixedSizeList ( _, _) => {
475
486
fixed_size_list_array_to_vector (
476
487
as_fixed_size_list_array ( column. as_ref ( ) ) ,
477
488
& mut out. list_vector_child ( i) ,
478
- ) ;
489
+ ) ? ;
479
490
}
480
491
DataType :: Struct ( _) => {
481
492
let struct_array = as_struct_array ( column. as_ref ( ) ) ;
482
493
let mut struct_vector = out. struct_vector_child ( i) ;
483
- struct_array_to_vector ( struct_array, & mut struct_vector) ;
494
+ struct_array_to_vector ( struct_array, & mut struct_vector) ? ;
484
495
}
485
496
_ => {
486
497
unimplemented ! (
@@ -490,6 +501,7 @@ fn struct_array_to_vector(array: &StructArray, out: &mut StructVector) {
490
501
}
491
502
}
492
503
}
504
+ Ok ( ( ) )
493
505
}
494
506
495
507
/// Pass RecordBatch to duckdb.
@@ -531,11 +543,11 @@ mod test {
531
543
use crate :: { Connection , Result } ;
532
544
use arrow:: {
533
545
array:: {
534
- Array , ArrayRef , AsArray , Date32Array , Date64Array , Float64Array , Int32Array , PrimitiveArray , StringArray ,
535
- StructArray , Time32SecondArray , Time64MicrosecondArray , TimestampMicrosecondArray ,
536
- TimestampMillisecondArray , TimestampNanosecondArray , TimestampSecondArray ,
546
+ Array , ArrayRef , AsArray , Date32Array , Date64Array , Decimal256Array , Float64Array , Int32Array ,
547
+ PrimitiveArray , StringArray , StructArray , Time32SecondArray , Time64MicrosecondArray ,
548
+ TimestampMicrosecondArray , TimestampMillisecondArray , TimestampNanosecondArray , TimestampSecondArray ,
537
549
} ,
538
- datatypes:: { ArrowPrimitiveType , DataType , Field , Fields , Schema } ,
550
+ datatypes:: { i256 , ArrowPrimitiveType , DataType , Field , Fields , Schema } ,
539
551
record_batch:: RecordBatch ,
540
552
} ;
541
553
use std:: { error:: Error , sync:: Arc } ;
@@ -749,4 +761,32 @@ mod test {
749
761
assert_eq ! ( column. value( 0 ) , "TIMESTAMP WITH TIME ZONE" ) ;
750
762
Ok ( ( ) )
751
763
}
764
+
765
+ #[ test]
766
+ fn test_arrow_error ( ) {
767
+ let arc: ArrayRef = Arc :: new ( Decimal256Array :: from ( vec ! [ i256:: from( 1 ) , i256:: from( 2 ) , i256:: from( 3 ) ] ) ) ;
768
+ let batch = RecordBatch :: try_from_iter ( vec ! [ ( "x" , arc) ] ) . unwrap ( ) ;
769
+
770
+ let db = Connection :: open_in_memory ( ) . unwrap ( ) ;
771
+ db. register_table_function :: < ArrowVTab > ( "arrow" ) . unwrap ( ) ;
772
+
773
+ let mut stmt = db. prepare ( "SELECT * FROM arrow(?, ?)" ) . unwrap ( ) ;
774
+
775
+ let res = match stmt. execute ( arrow_recordbatch_to_query_params ( batch) ) {
776
+ Ok ( ..) => None ,
777
+ Err ( e) => Some ( e) ,
778
+ }
779
+ . unwrap ( ) ;
780
+
781
+ assert_eq ! (
782
+ res,
783
+ crate :: error:: Error :: DuckDBFailure (
784
+ crate :: ffi:: Error {
785
+ code: crate :: ffi:: ErrorCode :: Unknown ,
786
+ extended_code: 1
787
+ } ,
788
+ Some ( "Invalid Input Error: Data type \" Decimal256(76, 10)\" not yet supported by ArrowVTab" . to_owned( ) )
789
+ )
790
+ ) ;
791
+ }
752
792
}
0 commit comments