1use std::collections::BTreeSet;
5use std::ops::Range;
6use std::sync::Arc;
7
8use async_trait::async_trait;
9use once_cell::sync::OnceCell;
10use vortex_array::ArrayRef;
11use vortex_array::stats::Precision;
12use vortex_dtype::{DType, FieldMask};
13use vortex_error::{VortexResult, vortex_bail};
14use vortex_expr::ExprRef;
15use vortex_mask::Mask;
16
17use crate::MaskFuture;
18use crate::children::LayoutChildren;
19use crate::segments::SegmentSource;
20
21pub type LayoutReaderRef = Arc<dyn LayoutReader>;
22
23pub trait LayoutReader: 'static + Send + Sync {
26 fn name(&self) -> &Arc<str>;
28
29 fn dtype(&self) -> &DType;
31
32 fn row_count(&self) -> Precision<u64>;
35
36 fn register_splits(
39 &self,
40 field_mask: &[FieldMask],
41 row_offset: u64,
42 splits: &mut BTreeSet<u64>,
43 ) -> VortexResult<()>;
44
45 fn pruning_evaluation(
47 &self,
48 row_range: &Range<u64>,
49 expr: &ExprRef,
50 ) -> VortexResult<Box<dyn PruningEvaluation>>;
51
52 fn filter_evaluation(
54 &self,
55 row_range: &Range<u64>,
56 expr: &ExprRef,
57 ) -> VortexResult<Box<dyn MaskEvaluation>>;
58
59 fn projection_evaluation(
61 &self,
62 row_range: &Range<u64>,
63 expr: &ExprRef,
64 ) -> VortexResult<Box<dyn ArrayEvaluation>>;
65}
66
67#[async_trait]
71pub trait PruningEvaluation: 'static + Send + Sync {
72 async fn invoke(&self, mask: Mask) -> VortexResult<Mask>;
73}
74
75pub struct NoOpPruningEvaluation;
76
77#[async_trait]
78impl PruningEvaluation for NoOpPruningEvaluation {
79 async fn invoke(&self, mask: Mask) -> VortexResult<Mask> {
80 Ok(mask)
81 }
82}
83
84#[async_trait]
94pub trait MaskEvaluation: 'static + Send + Sync {
95 async fn invoke(&self, mask: MaskFuture) -> VortexResult<Mask>;
96}
97
98pub struct NoOpMaskEvaluation;
99
100#[async_trait]
101impl MaskEvaluation for NoOpMaskEvaluation {
102 async fn invoke(&self, mask: MaskFuture) -> VortexResult<Mask> {
103 mask.await
104 }
105}
106
107#[async_trait]
117pub trait ArrayEvaluation: 'static + Send + Sync {
118 async fn invoke(&self, mask: MaskFuture) -> VortexResult<ArrayRef>;
119}
120
121pub struct LazyReaderChildren {
122 children: Arc<dyn LayoutChildren>,
123 segment_source: Arc<dyn SegmentSource>,
124
125 cache: Vec<OnceCell<LayoutReaderRef>>,
127}
128
129impl LazyReaderChildren {
130 pub fn new(children: Arc<dyn LayoutChildren>, segment_source: Arc<dyn SegmentSource>) -> Self {
131 let nchildren = children.nchildren();
132 let cache = (0..nchildren).map(|_| OnceCell::new()).collect();
133 Self {
134 children,
135 segment_source,
136 cache,
137 }
138 }
139
140 pub fn get(
141 &self,
142 idx: usize,
143 dtype: &DType,
144 name: &Arc<str>,
145 ) -> VortexResult<&LayoutReaderRef> {
146 if idx >= self.cache.len() {
147 vortex_bail!("Child index out of bounds: {} of {}", idx, self.cache.len());
148 }
149
150 self.cache[idx].get_or_try_init(|| {
151 let child = self.children.child(idx, dtype)?;
152 child.new_reader(name.clone(), self.segment_source.clone())
153 })
154 }
155}