Skip to content

Commit d7438c7

Browse files
authored
Fixes the issue ignoring nulls when copy from arrow array to flat vector (#316)
* null fix after copying data from array to duckdb chunk * add test to cover null cases
1 parent bbc85d7 commit d7438c7

File tree

1 file changed

+31
-1
lines changed

1 file changed

+31
-1
lines changed

src/vtab/arrow.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,13 @@ pub fn record_batch_to_duckdb_data_chunk(
257257
fn primitive_array_to_flat_vector<T: ArrowPrimitiveType>(array: &PrimitiveArray<T>, out_vector: &mut FlatVector) {
258258
// assert!(array.len() <= out_vector.capacity());
259259
out_vector.copy::<T::Native>(array.values());
260+
if let Some(nulls) = array.nulls() {
261+
for (i, null) in nulls.into_iter().enumerate() {
262+
if !null {
263+
out_vector.set_null(i);
264+
}
265+
}
266+
}
260267
}
261268

262269
fn primitive_array_to_flat_vector_cast<T: ArrowPrimitiveType>(
@@ -267,6 +274,13 @@ fn primitive_array_to_flat_vector_cast<T: ArrowPrimitiveType>(
267274
let array = arrow::compute::kernels::cast::cast(array, &data_type).unwrap();
268275
let out_vector: &mut FlatVector = out_vector.as_mut_any().downcast_mut().unwrap();
269276
out_vector.copy::<T::Native>(array.as_primitive::<T>().values());
277+
if let Some(nulls) = array.nulls() {
278+
for (i, null) in nulls.iter().enumerate() {
279+
if !null {
280+
out_vector.set_null(i);
281+
}
282+
}
283+
}
270284
}
271285

272286
fn primitive_array_to_vector(array: &dyn Array, out: &mut dyn Vector) -> Result<(), Box<dyn std::error::Error>> {
@@ -655,7 +669,7 @@ mod test {
655669
db.register_table_function::<ArrowVTab>("arrow")?;
656670

657671
// Roundtrip a record batch from Rust to DuckDB and back to Rust
658-
let schema = Schema::new(vec![Field::new("a", input_array.data_type().clone(), false)]);
672+
let schema = Schema::new(vec![Field::new("a", input_array.data_type().clone(), true)]);
659673

660674
let rb = RecordBatch::try_new(Arc::new(schema), vec![Arc::new(input_array.clone())])?;
661675
let param = arrow_recordbatch_to_query_params(rb);
@@ -746,6 +760,22 @@ mod test {
746760
Ok(())
747761
}
748762

763+
#[test]
764+
fn test_primitive_roundtrip_contains_nulls() -> Result<(), Box<dyn Error>> {
765+
let mut builder = arrow::array::PrimitiveBuilder::<arrow::datatypes::Int32Type>::new();
766+
builder.append_value(1);
767+
builder.append_null();
768+
builder.append_value(3);
769+
builder.append_null();
770+
builder.append_null();
771+
builder.append_value(6);
772+
let array = builder.finish();
773+
774+
check_rust_primitive_array_roundtrip(array.clone(), array)?;
775+
776+
Ok(())
777+
}
778+
749779
#[test]
750780
fn test_timestamp_roundtrip() -> Result<(), Box<dyn Error>> {
751781
check_rust_primitive_array_roundtrip(Int32Array::from(vec![1, 2, 3]), Int32Array::from(vec![1, 2, 3]))?;

0 commit comments

Comments
 (0)