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::{Value, 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::collections::HashMap;
18use std::sync::{Arc, Mutex};
19
20use super::{SchemaDdlFn, SequenceFn, StandaloneCallHandler, SubqueryFn};
21
22pub struct ExecutionContext<'p> {
24 pub processor: &'p QueryProcessor,
25 pub function_registry: Option<Arc<Mutex<FunctionRegistry>>>,
26 pub table_catalog: Option<Arc<TableCatalog>>,
27 pub vfs: Option<Arc<akar_common::file_system::VirtualFileSystemRegistry>>,
28 pub standalone_call_handler: Option<Arc<dyn StandaloneCallHandler>>,
29 pub sequence_fn: Option<SequenceFn>,
30 pub subquery_fn: Option<SubqueryFn>,
31 pub schema_ddl_fn: Option<SchemaDdlFn>,
32 pub snapshot_ts: Option<u64>,
35 pub commit_history: HashMap<u64, u64>,
37 pub written_rows: Vec<(u64, u64)>,
41 pub txn_id: Option<u64>,
44}
45
46impl<'p> ExecutionContext<'p> {
47 pub fn execute_children(&mut self, operators: &[LogicalOperator]) -> Result<Vec<DataChunk>, ProcessorError> {
48 self.processor.execute_internal(operators)
49 }
50
51 pub fn resolve_scan_data<'b>(
54 &self,
55 table_name: &str,
56 predicate: Option<(usize, &'b str, &'b akar_common::types::Value)>,
57 ) -> (
58 Option<Vec<Vec<akar_common::types::Value>>>,
59 Vec<akar_storage::table::ColumnDefinition>,
60 u64,
61 ) {
62 if let Some(ref tc) = self.table_catalog {
63 if let Some(node_table) = tc.get_node_table_by_name(table_name) {
65 let num_rows = node_table.num_rows;
66 if num_rows > 0 {
67 let (mut data, ids) = if self.snapshot_ts.is_some() {
69 node_table.to_column_major_data_with_snapshot_and_predicate_and_ids(
70 predicate,
71 self.snapshot_ts,
72 &self.commit_history,
73 )
74 } else {
75 node_table.to_column_major_data_with_predicate_and_ids(predicate)
76 };
77 data.push(ids.into_iter().map(|id| Value::Int64(id as i64)).collect());
81 let mut columns = node_table.columns.clone();
82 columns.push(akar_storage::table::ColumnDefinition {
83 name: "_id".to_string(),
84 logical_type: akar_common::types::LogicalTypeID::Int64,
85 is_primary_key: false,
86 compression: akar_common::enums::CompressionType::Uncompressed,
87 });
88 return (Some(data), columns, num_rows);
89 }
90 }
91 if let Some(rel_table) = tc.get_rel_table_by_name(table_name) {
93 let num_rows = rel_table.num_rows;
94 if num_rows > 0 {
95 return (
96 Some(rel_table.to_column_major_data()),
97 rel_table.columns.clone(),
98 num_rows,
99 );
100 }
101 }
102 }
103 (None, Vec::new(), 0)
104 }
105
106 pub fn resolve_scan_arrow_data(
116 &self,
117 table_name: &str,
118 ) -> (Option<Vec<ArrayRef>>, Vec<akar_storage::table::ColumnDefinition>, u64) {
119 if self.snapshot_ts.is_some() {
123 return (None, Vec::new(), 0);
124 }
125
126 if let Some(ref tc) = self.table_catalog {
127 if let Some(node_table) = tc.get_node_table_by_name(table_name) {
128 let num_rows = node_table.num_rows;
129 if num_rows > 0 {
130 let mut column_arrays: Vec<Vec<ArrayRef>> = vec![Vec::new(); node_table.columns.len()];
131 for ng in &node_table.node_groups {
132 for (col_idx, col_chunk) in ng.columns.iter().enumerate() {
133 let phys_type = physical_type_from_logical(node_table.columns[col_idx].logical_type);
134 let arr = col_chunk.to_arrow_array(phys_type);
135 column_arrays[col_idx].push(arr);
136 }
137 }
138 let mut concat_arrays: Vec<ArrayRef> = column_arrays
140 .into_iter()
141 .map(|group_arrays| {
142 if group_arrays.len() == 1 {
143 group_arrays.into_iter().next().unwrap()
144 } else {
145 let refs: Vec<&dyn arrow::array::Array> =
146 group_arrays.iter().map(|a| a.as_ref()).collect();
147 arrow::compute::concat(&refs)
148 .unwrap_or_else(|_| group_arrays.into_iter().next().unwrap())
149 }
150 })
151 .collect();
152 let id_array: ArrayRef = std::sync::Arc::new(arrow::array::Int64Array::from(
156 (0..num_rows as i64).collect::<Vec<i64>>(),
157 ));
158 concat_arrays.push(id_array);
159 let mut columns = node_table.columns.clone();
160 columns.push(akar_storage::table::ColumnDefinition {
161 name: "_id".to_string(),
162 logical_type: akar_common::types::LogicalTypeID::Int64,
163 is_primary_key: false,
164 compression: akar_common::enums::CompressionType::Uncompressed,
165 });
166 return (Some(concat_arrays), columns, num_rows);
167 }
168 }
169 }
170 (None, Vec::new(), 0)
171 }
172}
173
174pub struct PlanMapper;
175
176impl PlanMapper {
177 pub fn map_and_execute(
178 op: &LogicalOperator,
179 next_op: Option<&LogicalOperator>,
180 current_input: Vec<DataChunk>,
181 ctx: &mut ExecutionContext,
182 ) -> Result<Vec<DataChunk>, ProcessorError> {
183 match op {
184 LogicalOperator::ScanNode(s) => map_scan::map_and_execute_scan_node(s, next_op, current_input, ctx),
186 LogicalOperator::ScanRel(_)
187 | LogicalOperator::VectorSimilarityScan(_)
188 | LogicalOperator::ArtIndexRangeScan(_)
189 | LogicalOperator::IndexLookup(_)
190 | LogicalOperator::ExpressionsScan(_)
191 | LogicalOperator::PathPropertyProbe(_) => map_scan::map_and_execute_scan(op, current_input, ctx),
192
193 LogicalOperator::HashJoin(_)
195 | LogicalOperator::SemiJoin(_)
196 | LogicalOperator::AntiJoin(_)
197 | LogicalOperator::Intersect(_)
198 | LogicalOperator::CrossProduct(_)
199 | LogicalOperator::OptionalMatch(_)
200 | LogicalOperator::RecursiveExtend(_) => map_join::map_and_execute_join(op, current_input, ctx),
201
202 LogicalOperator::Aggregate(_) | LogicalOperator::CountRelTable(_) => {
204 map_aggregate::map_and_execute_aggregate(op, current_input, ctx)
205 }
206
207 LogicalOperator::Set(_)
209 | LogicalOperator::Delete(_)
210 | LogicalOperator::CreateNode(_)
211 | LogicalOperator::CreateRel(_)
212 | LogicalOperator::Merge(_)
213 | LogicalOperator::MergeRel(_)
214 | LogicalOperator::Extend(_)
215 | LogicalOperator::OptionalExtend(_)
216 | LogicalOperator::BatchInsert(_)
217 | LogicalOperator::Insert(_)
218 | LogicalOperator::CopyFrom(_) => map_update::map_and_execute_update(op, current_input, ctx),
219
220 LogicalOperator::Union(u) => {
222 use crate::processor::union_helpers::{flatten_union_child, merge_union_chunks};
223 let left_ops = flatten_union_child(&u.left);
224 let right_ops = flatten_union_child(&u.right);
225 let left = ctx.execute_children(&left_ops)?;
226 let right = ctx.execute_children(&right_ops)?;
227 merge_union_chunks(left, right, u.all)
228 }
229
230 LogicalOperator::Projection(_)
232 | LogicalOperator::Filter(_)
233 | LogicalOperator::TopK(_)
234 | LogicalOperator::OrderBy(_)
235 | LogicalOperator::Limit(_)
236 | LogicalOperator::Flatten(_)
237 | LogicalOperator::Unwind(_)
238 | LogicalOperator::Partitioner(_) => map_projection::map_and_execute_projection(op, current_input, ctx),
239
240 LogicalOperator::CreateNodeTable(_)
242 | LogicalOperator::CreateRelTable(_)
243 | LogicalOperator::DropTable(_)
244 | LogicalOperator::AlterTable(_)
245 | LogicalOperator::CreateIndex(_)
246 | LogicalOperator::DropIndex(_)
247 | LogicalOperator::CreateVectorIndex(_)
248 | LogicalOperator::CreateSequence(_)
249 | LogicalOperator::DropSequence(_)
250 | LogicalOperator::CreateDml(_)
251 | LogicalOperator::ExportDatabase(_)
252 | LogicalOperator::ImportDatabase(_)
253 | LogicalOperator::CreateFtsIndex(_)
254 | LogicalOperator::FtsScan(_)
255 | LogicalOperator::EmptyResult(_)
256 | LogicalOperator::MultiplicityReducer(_)
257 | LogicalOperator::Skip(_)
258 | LogicalOperator::ExtensionClause(_)
259 | LogicalOperator::StandaloneCall(_)
260 | LogicalOperator::TableFunctionCall(_)
261 | LogicalOperator::Foreach(_)
262 | LogicalOperator::Explain(_) => map_ddl::map_and_execute_ddl(op, current_input, ctx),
263
264 LogicalOperator::Accumulate(_) => {
265 let result = crate::physical_operator::PhysicalAccumulate.execute(current_input)?;
266 Ok(result)
267 }
268 }
269 }
270}