Skip to content

Commit 7968c7e

Browse files
committed
Push expressions through chunked and row-index plans
Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
1 parent 8b61834 commit 7968c7e

7 files changed

Lines changed: 484 additions & 356 deletions

File tree

vortex-layout/src/plan/children.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,24 @@ impl LazyPlanChildren {
4646
Ok(cell.get_or_try_init(|| (self.initializer)(index))?.clone())
4747
}
4848

49-
/// Lazily transforms each present child into a new child collection.
50-
pub(crate) fn map(
49+
/// Eagerly transforms each present child into a new child collection.
50+
pub(crate) fn try_map(
5151
&self,
52-
transform: impl Fn(usize, PlanRef) -> VortexResult<PlanRef> + 'static + Send + Sync,
53-
) -> Self {
54-
let source = self.clone();
55-
Self::new(self.len(), move |index| {
56-
source
57-
.get(index)?
58-
.map(|child| transform(index, child))
59-
.transpose()
60-
})
52+
transform: impl Fn(usize, PlanRef) -> VortexResult<PlanRef>,
53+
) -> VortexResult<Self> {
54+
// TODO: Make recursive child optimization lazy again once the optimizer API can
55+
// explicitly distinguish fully optimized plans from plans with deferred optimizer work.
56+
let children = (0..self.len())
57+
.map(|index| {
58+
self.get(index)?
59+
.map(|child| transform(index, child))
60+
.transpose()
61+
})
62+
.collect::<VortexResult<Vec<_>>>()?;
63+
let children: Arc<[Option<PlanRef>]> = children.into();
64+
let len = children.len();
65+
Ok(Self::new(len, move |index| {
66+
Ok(children.get(index).cloned().flatten())
67+
}))
6168
}
6269
}

vortex-layout/src/plan/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ pub use plans::DictPlan;
2323
pub use plans::ExpressionPlan;
2424
pub use plans::FlatPlan;
2525
pub use plans::ListPlan;
26+
pub use plans::RowIdxPartitionPlan;
2627
pub use plans::RowIdxPlan;
28+
pub use plans::RowIdxValuesPlan;
2729
pub use plans::StructPlan;
2830
use vortex_array::dtype::DType;
2931
use vortex_array::expr::Expression;
@@ -56,16 +58,14 @@ pub trait Plan: 'static + Send + Sync {
5658
std::any::type_name::<Self>()
5759
}
5860

59-
/// Optimizes this plan while preserving its dtype and row domain.
60-
///
61-
/// Implementations may defer child optimization until the child is accessed.
61+
/// Recursively optimizes this plan and all of its children while preserving its dtype and row
62+
/// domain.
6263
fn optimize(&self) -> VortexResult<PlanRef>;
6364

6465
/// Attempts to rewrite `expression` through this plan.
6566
///
66-
/// Returns `None` when this plan has no applicable expression rewrite. Implementations may
67-
/// request only the children needed by the rewrite and should preserve all other lazy child
68-
/// slots.
67+
/// Returns `None` when this plan has no applicable expression rewrite. Implementations should
68+
/// preserve child slots that the rewrite does not change.
6969
fn optimize_expression(&self, expression: &Expression) -> VortexResult<Option<PlanRef>> {
7070
let _ = expression;
7171
Ok(None)

vortex-layout/src/plan/plans/chunked.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ use std::borrow::Cow;
55
use std::sync::Arc;
66

77
use vortex_array::dtype::DType;
8+
use vortex_array::expr::Expression;
9+
use vortex_array::expr::label_tree;
810
use vortex_error::VortexResult;
911

1012
use crate::layouts::chunked::ChunkedLayout;
13+
use crate::layouts::row_idx::RowIdx;
14+
use crate::plan::ExpressionPlan;
1115
use crate::plan::LazyPlanChildren;
1216
use crate::plan::Plan;
1317
use crate::plan::PlanRef;
@@ -36,10 +40,10 @@ impl ChunkedPlan {
3640
}
3741
}
3842

39-
fn with_chunks(&self, chunks: LazyPlanChildren) -> Self {
43+
fn with_chunks(&self, dtype: DType, chunks: LazyPlanChildren) -> Self {
4044
Self {
4145
layout: self.layout.clone(),
42-
dtype: self.dtype.clone(),
46+
dtype,
4347
chunks,
4448
}
4549
}
@@ -55,8 +59,28 @@ impl Plan for ChunkedPlan {
5559
}
5660

5761
fn optimize(&self) -> VortexResult<PlanRef> {
58-
let chunks = self.chunks.map(|_, chunk| chunk.optimize());
59-
Ok(Arc::new(self.with_chunks(chunks)))
62+
let chunks = self.chunks.try_map(|_, chunk| chunk.optimize())?;
63+
Ok(Arc::new(self.with_chunks(self.dtype.clone(), chunks)))
64+
}
65+
66+
fn optimize_expression(&self, expression: &Expression) -> VortexResult<Option<PlanRef>> {
67+
let references_row_idx = label_tree(
68+
expression,
69+
|node| node.is::<RowIdx>(),
70+
|acc, &child| acc | child,
71+
)
72+
.get(expression)
73+
.copied()
74+
.unwrap_or(false);
75+
if references_row_idx {
76+
return Ok(None);
77+
}
78+
79+
let dtype = expression.return_dtype(&self.dtype)?;
80+
let chunks = self
81+
.chunks
82+
.try_map(|_, chunk| ExpressionPlan::try_new(expression.clone(), chunk)?.optimize())?;
83+
Ok(Some(Arc::new(self.with_chunks(dtype, chunks))))
6084
}
6185

6286
fn dtype(&self) -> &DType {

vortex-layout/src/plan/plans/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,7 @@ pub use dict::DictPlan;
1414
pub use expression::ExpressionPlan;
1515
pub use flat::FlatPlan;
1616
pub use list::ListPlan;
17+
pub use row_idx::RowIdxPartitionPlan;
1718
pub use row_idx::RowIdxPlan;
19+
pub use row_idx::RowIdxValuesPlan;
1820
pub use struct_::StructPlan;

0 commit comments

Comments
 (0)