1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
//! The planner takes a parsed query and makes it into a set of commands that can be sequentially executed.
use super::objects::{
    CommandType, JoinType, ModifyTablePlan, Plan, PlannedCommon, PlannedStatement, QueryTree,
    RangeRelation,
};
use crate::engine::objects::FullTableScan;
use std::sync::Arc;
use thiserror::Error;

pub struct Planner {}

impl Planner {
    pub fn plan(query_tree: QueryTree) -> Result<PlannedStatement, PlannerError> {
        match query_tree.command_type {
            CommandType::Insert => {
                return Planner::plan_insert(query_tree);
            }
            CommandType::Select => {
                return Planner::plan_select(query_tree);
            }
            _ => {
                return Err(PlannerError::NotImplemented());
            }
        }
    }

    fn plan_insert(query_tree: QueryTree) -> Result<PlannedStatement, PlannerError> {
        //So we know we want to insert, now the question is into what.
        //I'm going to start with a simple insert and let it evolve.

        //So we should be able to find a join for our table target
        let join = query_tree
            .joins
            .first()
            .ok_or_else(|| PlannerError::TooManyJoins(query_tree.joins.len()))?;

        match join {
            (JoinType::Inner, RangeRelation::Table(t), RangeRelation::AnonymousTable(at)) => {
                return Ok(PlannedStatement {
                    common: PlannedCommon {},
                    plan: Arc::new(Plan::ModifyTable(ModifyTablePlan {
                        table: t.table.clone(),
                        source: Arc::new(Plan::StaticData(at.clone())),
                    })),
                });
            }
            (_, _, _) => return Err(PlannerError::NotImplemented()),
        }
    }

    fn plan_select(query_tree: QueryTree) -> Result<PlannedStatement, PlannerError> {
        //TODO I'm ignoring joins at the moment

        //let mut targets = vec![];
        //for t in query_tree.targets {
        //    match t {
        //        TargetEntry::Parameter(p) => targets.push(p),
        //    }
        //}

        let mut unjoined = vec![];
        for rr in query_tree.range_tables {
            match rr {
                RangeRelation::Table(rrt) => {
                    unjoined.push(Arc::new(Plan::FullTableScan(FullTableScan {
                        src_table: rrt.table,
                        target_type: query_tree.targets.clone(), //TODO I know not every table needs every column
                    })));
                }
                RangeRelation::AnonymousTable(anon_tbl) => {
                    unjoined.push(Arc::new(Plan::StaticData(anon_tbl.clone())));
                }
            }
        }

        if unjoined.len() == 0 {
            return Err(PlannerError::NoDataProvided());
        } else if unjoined.len() == 1 {
            return Ok(PlannedStatement {
                common: PlannedCommon {},
                plan: unjoined[0].clone(),
            });
        } else {
            //let cart_joins = return Ok(PlannedStatement {
            //    common: PlannedCommon {},
            //    plan: Arc::new(Plan::CrossProduct(CrossProduct {
            //        columns: targets,
            //        source: unjoined,
            //    })),
            //});
            return Err(PlannerError::NotImplemented());
        }
    }
}

#[derive(Debug, Error)]
pub enum PlannerError {
    #[error("No data provided")]
    NoDataProvided(),
    #[error("Too Many Joins {0}")]
    TooManyJoins(usize),
    #[error("Not Implemented")]
    NotImplemented(),
}