This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push:
new fea605cb16 [Variant] Fix cast logic for Variant to Arrow for
DataType::Null (#8825)
fea605cb16 is described below
commit fea605cb16f7524cb69a197bfa581a1d4f5fe5d0
Author: Congxian Qiu <[email protected]>
AuthorDate: Thu Nov 20 02:17:12 2025 +0800
[Variant] Fix cast logic for Variant to Arrow for DataType::Null (#8825)
# Which issue does this PR close?
- Closes #8810 .
# What changes are included in this PR?
Fix the logic for `VariantToNullArrowRowBuilder` so that it respects the
`cast` option
# Are these changes tested?
added test
# Are there any user-facing changes?
Noe
---
parquet-variant-compute/src/variant_get.rs | 38 +++++++++++++++++++++++++
parquet-variant-compute/src/variant_to_arrow.rs | 21 ++++++++------
2 files changed, 51 insertions(+), 8 deletions(-)
diff --git a/parquet-variant-compute/src/variant_get.rs
b/parquet-variant-compute/src/variant_get.rs
index b082035ac0..82f02c3df8 100644
--- a/parquet-variant-compute/src/variant_get.rs
+++ b/parquet-variant-compute/src/variant_get.rs
@@ -319,6 +319,7 @@ mod test {
use arrow::compute::CastOptions;
use arrow::datatypes::DataType::{Int16, Int32, Int64};
use arrow::datatypes::i256;
+ use arrow::util::display::FormatOptions;
use arrow_schema::DataType::{Boolean, Float32, Float64, Int8};
use arrow_schema::{DataType, Field, FieldRef, Fields, IntervalUnit,
TimeUnit};
use chrono::DateTime;
@@ -1039,6 +1040,43 @@ mod test {
arrow::array::NullArray::new(3)
);
+
perfectly_shredded_variant_array_fn!(perfectly_shredded_null_variant_array_with_int,
|| {
+ Int32Array::from(vec![Some(32), Some(64), Some(48)])
+ });
+
+ // We append null values if type miss match happens in safe mode
+ perfectly_shredded_to_arrow_primitive_test!(
+ get_variant_perfectly_shredded_null_with_type_missmatch_in_safe_mode,
+ DataType::Null,
+ perfectly_shredded_null_variant_array_with_int,
+ arrow::array::NullArray::new(3)
+ );
+
+ // We'll return an error if type miss match happens in strict mode
+ #[test]
+ fn
get_variant_perfectly_shredded_null_as_null_with_type_missmatch_in_strict_mode()
{
+ let array = perfectly_shredded_null_variant_array_with_int();
+ let field = Field::new("typed_value", DataType::Null, true);
+ let options = GetOptions::new()
+ .with_as_type(Some(FieldRef::from(field)))
+ .with_cast_options(CastOptions {
+ safe: false,
+ format_options: FormatOptions::default(),
+ });
+
+ let result = variant_get(&array, options);
+
+ assert!(result.is_err());
+ let error_msg = format!("{}", result.unwrap_err());
+ assert!(
+ error_msg
+ .contains("Cast error: Failed to extract primitive of type
Null from variant Int32(32) at path VariantPath([])"),
+ "Expected=[Cast error: Failed to extract primitive of type Null
from variant Int32(32) at path VariantPath([])],\
+ Got error message=[{}]",
+ error_msg
+ );
+ }
+
perfectly_shredded_variant_array_fn!(perfectly_shredded_decimal4_variant_array,
|| {
Decimal32Array::from(vec![Some(12345), Some(23400), Some(-12342)])
.with_precision_and_scale(5, 2)
diff --git a/parquet-variant-compute/src/variant_to_arrow.rs
b/parquet-variant-compute/src/variant_to_arrow.rs
index 6b0e05dd26..9d158dd96d 100644
--- a/parquet-variant-compute/src/variant_to_arrow.rs
+++ b/parquet-variant-compute/src/variant_to_arrow.rs
@@ -696,24 +696,29 @@ impl VariantToBinaryVariantArrowRowBuilder {
}
}
-struct FakeNullBuilder(NullArray);
+#[derive(Default)]
+struct FakeNullBuilder {
+ item_count: usize,
+}
impl FakeNullBuilder {
- fn new(capacity: usize) -> Self {
- Self(NullArray::new(capacity))
+ fn append_value(&mut self, _: ()) {
+ self.item_count += 1;
+ }
+
+ fn append_null(&mut self) {
+ self.item_count += 1;
}
- fn append_value<T>(&mut self, _: T) {}
- fn append_null(&mut self) {}
fn finish(self) -> NullArray {
- self.0
+ NullArray::new(self.item_count)
}
}
define_variant_to_primitive_builder!(
struct VariantToNullArrowRowBuilder<'a>
- |capacity| -> FakeNullBuilder { FakeNullBuilder::new(capacity) },
- |_value| Some(Variant::Null),
+ |_capacity| -> FakeNullBuilder { FakeNullBuilder::default() },
+ |value| value.as_null(),
type_name: "Null"
);