feophantlib/engine/
planner.rs

1//! The planner takes a parsed query and makes it into a set of commands that can be sequentially executed.
2use super::objects::{
3    CommandType, JoinType, ModifyTablePlan, Plan, PlannedCommon, PlannedStatement, QueryTree,
4    RangeRelation,
5};
6use crate::engine::objects::FullTableScan;
7use std::sync::Arc;
8use thiserror::Error;
9
10pub struct Planner {}
11
12impl Planner {
13    pub fn plan(query_tree: QueryTree) -> Result<PlannedStatement, PlannerError> {
14        match query_tree.command_type {
15            CommandType::Insert => Planner::plan_insert(query_tree),
16            CommandType::Select => Planner::plan_select(query_tree),
17            _ => Err(PlannerError::NotImplemented()),
18        }
19    }
20
21    fn plan_insert(query_tree: QueryTree) -> Result<PlannedStatement, PlannerError> {
22        //So we know we want to insert, now the question is into what.
23        //I'm going to start with a simple insert and let it evolve.
24
25        //So we should be able to find a join for our table target
26        let join = query_tree
27            .joins
28            .first()
29            .ok_or_else(|| PlannerError::TooManyJoins(query_tree.joins.len()))?;
30
31        match join {
32            (JoinType::Inner, RangeRelation::Table(t), RangeRelation::AnonymousTable(at)) => {
33                Ok(PlannedStatement {
34                    common: PlannedCommon {},
35                    plan: Arc::new(Plan::ModifyTable(ModifyTablePlan {
36                        table: t.table.clone(),
37                        source: Arc::new(Plan::StaticData(at.clone())),
38                    })),
39                })
40            }
41            (_, _, _) => Err(PlannerError::NotImplemented()),
42        }
43    }
44
45    fn plan_select(query_tree: QueryTree) -> Result<PlannedStatement, PlannerError> {
46        //TODO I'm ignoring joins at the moment
47
48        //let mut targets = vec![];
49        //for t in query_tree.targets {
50        //    match t {
51        //        TargetEntry::Parameter(p) => targets.push(p),
52        //    }
53        //}
54
55        let mut unjoined = vec![];
56        for rr in query_tree.range_tables {
57            match rr {
58                RangeRelation::Table(rrt) => {
59                    unjoined.push(Arc::new(Plan::FullTableScan(FullTableScan {
60                        src_table: rrt.table,
61                        target_type: query_tree.targets.clone(), //TODO I know not every table needs every column
62                    })));
63                }
64                RangeRelation::AnonymousTable(anon_tbl) => {
65                    unjoined.push(Arc::new(Plan::StaticData(anon_tbl.clone())));
66                }
67            }
68        }
69
70        if unjoined.is_empty() {
71            Err(PlannerError::NoDataProvided())
72        } else if unjoined.len() == 1 {
73            Ok(PlannedStatement {
74                common: PlannedCommon {},
75                plan: unjoined[0].clone(),
76            })
77        } else {
78            //let cart_joins = return Ok(PlannedStatement {
79            //    common: PlannedCommon {},
80            //    plan: Arc::new(Plan::CrossProduct(CrossProduct {
81            //        columns: targets,
82            //        source: unjoined,
83            //    })),
84            //});
85            Err(PlannerError::NotImplemented())
86        }
87    }
88}
89
90#[derive(Debug, Error)]
91pub enum PlannerError {
92    #[error("No data provided")]
93    NoDataProvided(),
94    #[error("Too Many Joins {0}")]
95    TooManyJoins(usize),
96    #[error("Not Implemented")]
97    NotImplemented(),
98}