akar_processor/processor/mapper/
map_projection.rs1use super::ExecutionContext;
2use crate::expression_evaluator::ExpressionEvaluator;
3use crate::physical_operator::*;
4use crate::processor::projection_helper::resolve_projection_column_index;
5use akar_common::error::ProcessorError;
6use akar_common::vector::DataChunk;
7use akar_parser::ast::Expression;
8use akar_planner::logical_operator::LogicalOperator;
9use std::sync::{Arc, Mutex};
10
11fn projection_needs_expression_eval(expr: &Expression) -> bool {
12 matches!(
13 expr,
14 Expression::FunctionCall(_, _)
15 | Expression::Constant(_)
16 | Expression::BinaryOp(_, _, _)
17 | Expression::UnaryOp(_, _)
18 | Expression::List(_)
19 | Expression::Map(_)
20 | Expression::Parameter(_)
21 | Expression::ExistsSubquery(_)
22 | Expression::ListPredicate { .. }
23 )
24}
25
26pub fn map_and_execute_projection(
27 op: &LogicalOperator,
28 current_input: Vec<DataChunk>,
29 ctx: &mut ExecutionContext,
30) -> Result<Vec<DataChunk>, ProcessorError> {
31 match op {
32 LogicalOperator::Projection(p) => {
33 let input = if p.children.is_empty() {
34 current_input
35 } else {
36 ctx.execute_children(&p.children)?
37 };
38
39 let result = if p.expressions.is_empty() {
40 input
41 } else {
42 let needs_eval = p
43 .expressions
44 .iter()
45 .any(|be| projection_needs_expression_eval(&be.expression));
46
47 if needs_eval {
48 let registry = ctx
49 .function_registry
50 .clone()
51 .ok_or_else(|| "No function registry available for expression projection".to_string())?;
52
53 let mut eval = ExpressionEvaluator::new(registry);
54 if let Some(ref seq_fn) = ctx.sequence_fn {
55 eval = eval.with_sequence_fn(seq_fn.clone());
56 }
57 if let Some(ref subquery_fn) = ctx.subquery_fn {
58 eval = eval.with_subquery_fn(subquery_fn.clone());
59 }
60
61 let mut output = Vec::with_capacity(input.len());
62 for chunk in input {
63 let mut fields = Vec::with_capacity(p.expressions.len());
64 let mut field_types = Vec::with_capacity(p.expressions.len());
65 for be in &p.expressions {
66 let result_vec = eval.evaluate(&be.expression, &chunk)?;
67 let pt = result_vec.physical_type();
68 let arr = akar_common::arrow_vector::ArrowVector::from_legacy(&result_vec).array;
69 fields.push(arr);
70 field_types.push(pt);
71 }
72 let size = fields.first().map(|f| f.len()).unwrap_or(chunk.size);
73 output.push(DataChunk {
74 fields,
75 field_types,
76 size,
77 field_names: vec![],
78 sel_vector: None,
79 });
80 }
81 output
82 } else {
83 let column_indices: Vec<usize> = if let Some(first_chunk) = input.first() {
84 p.expressions
85 .iter()
86 .filter_map(|be| resolve_projection_column_index(&be.expression, first_chunk))
87 .collect()
88 } else {
89 Vec::new()
90 };
91 let column_indices = if column_indices.len() == p.expressions.len() {
92 column_indices
93 } else {
94 (0..p.expressions.len()).collect()
95 };
96 let proj = PhysicalProjection { column_indices };
97 proj.execute(input)?
98 }
99 };
100 Ok(result)
101 }
102 LogicalOperator::Filter(f) => {
103 let evaluator = ctx.function_registry.clone().map(|reg| {
104 let mut eval = ExpressionEvaluator::new(reg);
105 if let Some(ref seq_fn) = ctx.sequence_fn {
106 eval = eval.with_sequence_fn(seq_fn.clone());
107 }
108 if let Some(ref subquery_fn) = ctx.subquery_fn {
109 eval = eval.with_subquery_fn(subquery_fn.clone());
110 }
111 Arc::new(Mutex::new(eval))
112 });
113 let filter = if let Some(eval) = evaluator {
114 PhysicalFilter::with_evaluator(f.expression.clone(), eval)
115 } else {
116 PhysicalFilter::new(f.expression.clone())
117 };
118 let result = filter.execute(current_input)?;
119 Ok(result)
120 }
121 LogicalOperator::Limit(l) => {
122 let limit = PhysicalLimit {
123 limit: l.limit,
124 offset: l.offset,
125 };
126 let result = limit.execute(current_input)?;
127 Ok(result)
128 }
129 LogicalOperator::TopK(tk) => {
130 let sort_keys: Vec<(u32, bool)> = tk
131 .sort_keys
132 .iter()
133 .enumerate()
134 .map(|(i, _s)| (i as u32, tk.sort_keys.get(i).map(|s| s.1).unwrap_or(true)))
135 .collect();
136 let topk = PhysicalTopK {
137 sort_keys,
138 limit: tk.limit,
139 offset: tk.offset,
140 };
141 let result = topk.execute(current_input)?;
142 Ok(result)
143 }
144 LogicalOperator::OrderBy(o) => {
145 let sort_keys: Vec<(u32, bool)> = o
146 .sort_keys
147 .iter()
148 .enumerate()
149 .map(|(i, _s)| (i as u32, o.sort_keys.get(i).map(|s| s.1).unwrap_or(true)))
150 .collect();
151 let order = PhysicalOrderBy { sort_keys };
152 let result = order.execute(current_input)?;
153 Ok(result)
154 }
155 LogicalOperator::Flatten(f) => {
156 let input = if f.children.is_empty() {
157 current_input
158 } else {
159 ctx.execute_children(&f.children)?
160 };
161 let flatten = PhysicalFlatten::new(f.group_pos);
162 flatten.execute(input)
163 }
164 LogicalOperator::Unwind(uw) => {
165 let unwind = PhysicalUnwind {
166 expression: uw.expression.clone(),
167 variable: uw.variable.clone(),
168 };
169 let result = unwind.execute(current_input)?;
170 Ok(result)
171 }
172 LogicalOperator::Partitioner(p) => {
173 const MORSEL_SIZE: usize = 1024;
174 let partitioner = Partitioner::new(MORSEL_SIZE);
175 let morsels = partitioner.execute(current_input)?;
176
177 let mut results = Vec::new();
178 for _morsel in morsels {
179 let child_result = ctx.execute_children(&p.children)?;
180 results.extend(child_result);
181 }
182 Ok(results)
183 }
184 _ => Err(format!("Not a projection/filter operator: {:?}", op).into()),
185 }
186}