akar_processor/processor/mapper/
mod.rs1pub mod map_aggregate;
2pub mod map_ddl;
3pub mod map_join;
4pub mod map_projection;
5pub mod map_scan;
6pub mod map_update;
7
8use crate::physical::types::PhysicalOperatorExec;
9use crate::processor::QueryProcessor;
10use akar_common::error::ProcessorError;
11use akar_common::types::physical_type_from_logical;
12use akar_common::vector::DataChunk;
13use akar_function::registry::FunctionRegistry;
14use akar_planner::logical_operator::LogicalOperator;
15use akar_storage::table::TableCatalog;
16use arrow::array::ArrayRef;
17use std::sync::{Arc, Mutex};
18
19use super::{SchemaDdlFn, SequenceFn, StandaloneCallHandler, SubqueryFn};
20
21pub struct ExecutionContext<'p> {
23 pub processor: &'p QueryProcessor,
24 pub function_registry: Option<Arc<Mutex<FunctionRegistry>>>,
25 pub table_catalog: Option<Arc<TableCatalog>>,
26 pub vfs: Option<Arc<akar_common::file_system::VirtualFileSystemRegistry>>,
27 pub standalone_call_handler: Option<Arc<dyn StandaloneCallHandler>>,
28 pub sequence_fn: Option<SequenceFn>,
29 pub subquery_fn: Option<SubqueryFn>,
30 pub schema_ddl_fn: Option<SchemaDdlFn>,
31 pub snapshot_ts: Option<u64>,
34 pub commit_history: Vec<(u64, u64)>,
36 pub written_rows: Vec<(u64, u64)>,
40}
41
42impl<'p> ExecutionContext<'p> {
43 pub fn execute_children(&mut self, operators: &[LogicalOperator]) -> Result<Vec<DataChunk>, ProcessorError> {
44 self.processor.execute_internal(operators)
45 }
46
47 pub fn resolve_scan_data<'b>(
50 &self,
51 table_name: &str,
52 predicate: Option<(usize, &'b str, &'b akar_common::types::Value)>,
53 ) -> (
54 Option<Vec<Vec<akar_common::types::Value>>>,
55 Vec<akar_storage::table::ColumnDefinition>,
56 u64,
57 ) {
58 if let Some(ref tc) = self.table_catalog {
59 if let Some(node_table) = tc.get_node_table_by_name(table_name) {
61 let num_rows = node_table.num_rows;
62 if num_rows > 0 {
63 let data = if self.snapshot_ts.is_some() {
64 node_table.to_column_major_data_with_snapshot_and_predicate(
66 predicate,
67 self.snapshot_ts,
68 &self.commit_history,
69 )
70 } else {
71 node_table.to_column_major_data_with_predicate(predicate)
72 };
73 return (Some(data), node_table.columns.clone(), num_rows);
74 }
75 }
76 if let Some(rel_table) = tc.get_rel_table_by_name(table_name) {
78 let num_rows = rel_table.num_rows;
79 if num_rows > 0 {
80 return (
81 Some(rel_table.to_column_major_data()),
82 rel_table.columns.clone(),
83 num_rows,
84 );
85 }
86 }
87 }
88 (None, Vec::new(), 0)
89 }
90
91 pub fn resolve_scan_arrow_data(
101 &self,
102 table_name: &str,
103 ) -> (Option<Vec<ArrayRef>>, Vec<akar_storage::table::ColumnDefinition>, u64) {
104 if self.snapshot_ts.is_some() {
108 return (None, Vec::new(), 0);
109 }
110
111 if let Some(ref tc) = self.table_catalog {
112 if let Some(node_table) = tc.get_node_table_by_name(table_name) {
113 let num_rows = node_table.num_rows;
114 if num_rows > 0 {
115 let mut column_arrays: Vec<Vec<ArrayRef>> = vec![Vec::new(); node_table.columns.len()];
116 for ng in &node_table.node_groups {
117 for (col_idx, col_chunk) in ng.columns.iter().enumerate() {
118 let phys_type = physical_type_from_logical(node_table.columns[col_idx].logical_type);
119 let arr = col_chunk.to_arrow_array(phys_type);
120 column_arrays[col_idx].push(arr);
121 }
122 }
123 let concat_arrays: Vec<ArrayRef> = column_arrays
125 .into_iter()
126 .map(|group_arrays| {
127 if group_arrays.len() == 1 {
128 group_arrays.into_iter().next().unwrap()
129 } else {
130 let refs: Vec<&dyn arrow::array::Array> =
131 group_arrays.iter().map(|a| a.as_ref()).collect();
132 arrow::compute::concat(&refs)
133 .unwrap_or_else(|_| group_arrays.into_iter().next().unwrap())
134 }
135 })
136 .collect();
137 return (Some(concat_arrays), node_table.columns.clone(), num_rows);
138 }
139 }
140 }
141 (None, Vec::new(), 0)
142 }
143}
144
145pub struct PlanMapper;
146
147impl PlanMapper {
148 pub fn map_and_execute(
149 op: &LogicalOperator,
150 next_op: Option<&LogicalOperator>,
151 current_input: Vec<DataChunk>,
152 ctx: &mut ExecutionContext,
153 ) -> Result<Vec<DataChunk>, ProcessorError> {
154 match op {
155 LogicalOperator::ScanNode(s) => map_scan::map_and_execute_scan_node(s, next_op, current_input, ctx),
157 LogicalOperator::ScanRel(_)
158 | LogicalOperator::VectorSimilarityScan(_)
159 | LogicalOperator::ArtIndexRangeScan(_)
160 | LogicalOperator::IndexLookup(_)
161 | LogicalOperator::ExpressionsScan(_)
162 | LogicalOperator::PathPropertyProbe(_) => map_scan::map_and_execute_scan(op, current_input, ctx),
163
164 LogicalOperator::HashJoin(_)
166 | LogicalOperator::SemiJoin(_)
167 | LogicalOperator::AntiJoin(_)
168 | LogicalOperator::Intersect(_)
169 | LogicalOperator::CrossProduct(_)
170 | LogicalOperator::OptionalMatch(_)
171 | LogicalOperator::RecursiveExtend(_) => map_join::map_and_execute_join(op, current_input, ctx),
172
173 LogicalOperator::Aggregate(_) | LogicalOperator::CountRelTable(_) => {
175 map_aggregate::map_and_execute_aggregate(op, current_input, ctx)
176 }
177
178 LogicalOperator::Set(_)
180 | LogicalOperator::Delete(_)
181 | LogicalOperator::CreateNode(_)
182 | LogicalOperator::CreateRel(_)
183 | LogicalOperator::Merge(_)
184 | LogicalOperator::Extend(_)
185 | LogicalOperator::BatchInsert(_)
186 | LogicalOperator::Insert(_)
187 | LogicalOperator::CopyFrom(_) => map_update::map_and_execute_update(op, current_input, ctx),
188
189 LogicalOperator::Union(u) => {
191 use crate::processor::union_helpers::{flatten_union_child, merge_union_chunks};
192 let left_ops = flatten_union_child(&u.left);
193 let right_ops = flatten_union_child(&u.right);
194 let left = ctx.execute_children(&left_ops)?;
195 let right = ctx.execute_children(&right_ops)?;
196 merge_union_chunks(left, right, u.all)
197 }
198
199 LogicalOperator::Projection(_)
201 | LogicalOperator::Filter(_)
202 | LogicalOperator::TopK(_)
203 | LogicalOperator::OrderBy(_)
204 | LogicalOperator::Limit(_)
205 | LogicalOperator::Flatten(_)
206 | LogicalOperator::Unwind(_)
207 | LogicalOperator::Partitioner(_) => map_projection::map_and_execute_projection(op, current_input, ctx),
208
209 LogicalOperator::CreateNodeTable(_)
211 | LogicalOperator::CreateRelTable(_)
212 | LogicalOperator::DropTable(_)
213 | LogicalOperator::AlterTable(_)
214 | LogicalOperator::CreateIndex(_)
215 | LogicalOperator::DropIndex(_)
216 | LogicalOperator::CreateVectorIndex(_)
217 | LogicalOperator::CreateSequence(_)
218 | LogicalOperator::DropSequence(_)
219 | LogicalOperator::CreateDml(_)
220 | LogicalOperator::ExportDatabase(_)
221 | LogicalOperator::ImportDatabase(_)
222 | LogicalOperator::CreateFtsIndex(_)
223 | LogicalOperator::FtsScan(_)
224 | LogicalOperator::EmptyResult(_)
225 | LogicalOperator::MultiplicityReducer(_)
226 | LogicalOperator::Skip(_)
227 | LogicalOperator::ExtensionClause(_)
228 | LogicalOperator::StandaloneCall(_)
229 | LogicalOperator::TableFunctionCall(_)
230 | LogicalOperator::Foreach(_)
231 | LogicalOperator::Explain(_) => map_ddl::map_and_execute_ddl(op, current_input, ctx),
232
233 LogicalOperator::Accumulate(_) => {
234 let result = crate::physical_operator::PhysicalAccumulate.execute(current_input)?;
235 Ok(result)
236 }
237 }
238 }
239}