vortex_array/
optimizer.rs1use std::sync::Arc;
5
6use vortex_error::VortexResult;
7
8use crate::vtable::VTable;
9use crate::{Array, ArrayRef};
10
11impl dyn Array + '_ {
12 pub fn optimize(&self) -> VortexResult<ArrayRef> {
15 let slf = self.to_array();
16 let children = self.children();
17
18 let mut new_children = Vec::with_capacity(children.len());
19 let mut children_modified = false;
20 for (idx, child) in children.iter().enumerate() {
21 let child = child.optimize()?;
22
23 if let Some(reduced) = child.reduce_parent(&slf, idx)? {
25 return Ok(reduced);
26 }
27
28 if !Arc::ptr_eq(&child, &children[idx]) {
29 children_modified = true;
30 }
31 new_children.push(child);
32 }
33
34 if children_modified {
35 return self.with_children(&new_children);
36 }
37
38 Ok(slf)
39 }
40}
41
42pub trait ReduceParent<Parent: VTable, const CHILD_IDX: usize>: VTable {
45 fn reduce_parent(array: &Self::Array, parent: &Parent::Array)
49 -> VortexResult<Option<ArrayRef>>;
50}
51
52pub trait OptimizerRule {
54 fn optimize(&self, array: &ArrayRef) -> VortexResult<Option<ArrayRef>>;
58}
59
60#[cfg(test)]
61mod tests {
62 use vortex_buffer::{bitbuffer, buffer};
63 use vortex_dtype::PTypeDowncast;
64 use vortex_vector::VectorOps;
65
66 use crate::IntoArray;
67 use crate::arrays::{BoolArray, MaskedArray, PrimitiveArray};
68 use crate::validity::Validity;
69
70 #[test]
71 fn test_masked_pushdown() {
72 let array = PrimitiveArray::from_iter([0u32, 1, 2, 3]);
73 assert!(!array.dtype().is_nullable());
74
75 let masked = MaskedArray::try_new(
76 array.into_array(),
77 Validity::Array(BoolArray::from(bitbuffer![0 1 0 1]).into_array()),
78 )
79 .unwrap();
80
81 let result = masked.optimize().unwrap();
82 assert_eq!(masked.dtype(), result.dtype());
83 assert!(result.dtype().is_nullable());
84
85 let vector = result.execute().unwrap().into_primitive().into_u32();
86 assert_eq!(vector.elements(), &buffer![0, 1, 2, 3]);
87 assert_eq!(vector.validity().to_bit_buffer(), bitbuffer![0 1 0 1]);
88 }
89}