vortex_array/arrays/decimal/vtable/
operator.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use vortex_dtype::match_each_decimal_value_type;
5use vortex_error::VortexResult;
6
7use crate::ArrayRef;
8use crate::IntoArray;
9use crate::arrays::DecimalArray;
10use crate::arrays::DecimalVTable;
11use crate::arrays::MaskedArray;
12use crate::arrays::MaskedVTable;
13use crate::optimizer::rules::ArrayParentReduceRule;
14use crate::optimizer::rules::Exact;
15use crate::vtable::ValidityHelper;
16
17/// Rule to push down validity masking from MaskedArray parent into DecimalArray child.
18///
19/// When a DecimalArray is wrapped by a MaskedArray, this rule merges the mask's validity
20/// with the DecimalArray's existing validity, eliminating the need for the MaskedArray wrapper.
21#[derive(Default, Debug)]
22pub struct DecimalMaskedValidityRule;
23
24impl ArrayParentReduceRule<Exact<DecimalVTable>, Exact<MaskedVTable>>
25    for DecimalMaskedValidityRule
26{
27    fn child(&self) -> Exact<DecimalVTable> {
28        Exact::from(&DecimalVTable)
29    }
30
31    fn parent(&self) -> Exact<MaskedVTable> {
32        Exact::from(&MaskedVTable)
33    }
34
35    fn reduce_parent(
36        &self,
37        array: &DecimalArray,
38        parent: &MaskedArray,
39        _child_idx: usize,
40    ) -> VortexResult<Option<ArrayRef>> {
41        // Merge the parent's validity mask into the child's validity
42        // TODO(joe): make this lazy
43        let masked_array = match_each_decimal_value_type!(array.values_type(), |D| {
44            // SAFETY: Since we are only flipping some bits in the validity, all invariants that
45            // were upheld are still upheld.
46            unsafe {
47                DecimalArray::new_unchecked(
48                    array.buffer::<D>(),
49                    array.decimal_dtype(),
50                    array.validity().clone().and(parent.validity().clone()),
51                )
52            }
53            .into_array()
54        });
55
56        Ok(Some(masked_array))
57    }
58}