vortex_layout/plan/
lower.rs1use vortex_error::VortexResult;
10use vortex_error::vortex_bail;
11use vortex_error::vortex_err;
12
13use crate::LayoutRef;
14use crate::layouts::chunked::Chunked;
15use crate::layouts::chunked::ChunkedLayout;
16use crate::layouts::dict::Dict;
17use crate::layouts::dict::DictLayout;
18use crate::layouts::flat::Flat;
19use crate::layouts::flat::FlatLayout;
20use crate::layouts::list::ELEMENTS_CHILD_INDEX;
21use crate::layouts::list::List;
22use crate::layouts::list::ListLayout;
23use crate::layouts::list::OFFSETS_CHILD_INDEX;
24use crate::layouts::list::VALIDITY_CHILD_INDEX;
25use crate::layouts::struct_::Struct;
26use crate::layouts::struct_::StructLayout;
27use crate::plan::ConcatPlan;
28use crate::plan::ListPackPlan;
29use crate::plan::PackPlan;
30use crate::plan::PlanChildren;
31use crate::plan::PlanRef;
32use crate::plan::SegmentScanPlan;
33use crate::plan::TakePlan;
34
35pub fn lower(layout: &LayoutRef) -> VortexResult<PlanRef> {
40 if let Some(layout) = layout.as_opt::<Flat>() {
41 return Ok(lower_flat(layout).into_plan());
42 }
43 if let Some(layout) = layout.as_opt::<Chunked>() {
44 return Ok(lower_chunked(layout)?.into_plan());
45 }
46 if let Some(layout) = layout.as_opt::<Struct>() {
47 return Ok(lower_struct(layout)?.into_plan());
48 }
49 if let Some(layout) = layout.as_opt::<Dict>() {
50 return Ok(lower_dict(layout)?.into_plan());
51 }
52 if let Some(layout) = layout.as_opt::<List>() {
53 return Ok(lower_list(layout)?.into_plan());
54 }
55 vortex_bail!(
56 "No physical plan implementation for layout '{}'",
57 layout.encoding_id()
58 )
59}
60
61fn lower_flat(layout: &FlatLayout) -> SegmentScanPlan {
62 SegmentScanPlan::new(
63 layout.dtype().clone(),
64 layout.row_count(),
65 layout.segment_id(),
66 layout.array_ctx().clone(),
67 layout.array_tree().cloned(),
68 )
69}
70
71fn lower_chunked(layout: &ChunkedLayout) -> VortexResult<ConcatPlan> {
72 let mut row_offsets = Vec::with_capacity(layout.nchildren());
73 let mut row_count = 0u64;
74 for index in 0..layout.nchildren() {
75 row_offsets.push(row_count);
76 row_count = row_count
77 .checked_add(layout.child_row_count(index))
78 .ok_or_else(|| vortex_err!("Chunked row count overflow"))?;
79 }
80 Ok(unsafe {
83 ConcatPlan::from_children_unchecked(
84 layout.dtype().clone(),
85 layout.row_count(),
86 row_offsets.into(),
87 lazy_children(layout.to_layout(), (0..layout.nchildren()).collect()),
88 )
89 })
90}
91
92fn lower_struct(layout: &StructLayout) -> VortexResult<PackPlan> {
93 let fields = layout.struct_fields().clone();
96 let mut slots = (1..=fields.nfields()).collect::<Vec<_>>();
97 if layout.dtype().is_nullable() {
98 slots.push(0);
99 }
100 Ok(unsafe {
103 PackPlan::from_children_unchecked(
104 fields,
105 layout.dtype().nullability(),
106 layout.row_count(),
107 lazy_children(layout.to_layout(), slots),
108 )
109 })
110}
111
112fn lower_dict(layout: &DictLayout) -> VortexResult<TakePlan> {
113 Ok(unsafe {
118 TakePlan::from_children_unchecked(
119 layout.dtype().clone(),
120 layout.row_count(),
121 lazy_children(layout.to_layout(), vec![1, 0]),
122 )
123 })
124}
125
126fn lower_list(layout: &ListLayout) -> VortexResult<ListPackPlan> {
127 let mut slots = vec![ELEMENTS_CHILD_INDEX, OFFSETS_CHILD_INDEX];
128 if layout.dtype().is_nullable() {
129 slots.push(VALIDITY_CHILD_INDEX);
130 }
131 Ok(unsafe {
134 ListPackPlan::from_children_unchecked(
135 layout.dtype().clone(),
136 layout.row_count(),
137 lazy_children(layout.to_layout(), slots),
138 )
139 })
140}
141
142fn lazy_children(layout: LayoutRef, slots: Vec<usize>) -> PlanChildren {
143 PlanChildren::lazy(slots.len(), move |index| {
144 let slot = slots
145 .get(index)
146 .copied()
147 .ok_or_else(|| vortex_err!("Missing plan child slot {index}"))?;
148 let child = layout
149 .slot(slot)?
150 .ok_or_else(|| vortex_err!("Layout child slot {slot} is absent"))?;
151 lower(&child)
152 })
153}