quill_sql/plan/logical_planner/
logical_planner.rs1use crate::error::{QuillSQLError, QuillSQLResult};
2
3use crate::catalog::Catalog;
4use crate::plan::logical_plan::{LogicalPlan, OrderByExpr, TransactionModes, TransactionScope};
5use crate::sql::ast;
6use crate::sql::ast::Value;
7use crate::utils::table_ref::TableReference;
8use sqlparser::ast::ObjectType;
9
10pub struct PlannerContext<'a> {
11 pub catalog: &'a Catalog,
12}
13
14pub struct LogicalPlanner<'a> {
15 pub context: PlannerContext<'a>,
16}
17impl<'a> LogicalPlanner<'a> {
18 pub fn plan(&mut self, stmt: &ast::Statement) -> QuillSQLResult<LogicalPlan> {
19 match stmt {
20 ast::Statement::CreateTable {
21 name,
22 columns,
23 if_not_exists,
24 ..
25 } => self.plan_create_table(name, columns, *if_not_exists),
26 ast::Statement::CreateIndex {
27 name,
28 table_name,
29 columns,
30 ..
31 } => self.plan_create_index(name, table_name, columns),
32 ast::Statement::Drop {
33 object_type,
34 if_exists,
35 names,
36 cascade,
37 restrict: _,
38 purge,
39 } => match object_type {
40 ObjectType::Table => self.plan_drop_table(names, *if_exists, *cascade, *purge),
41 ObjectType::Index => self.plan_drop_index(names, *if_exists, *cascade, *purge),
42 other => Err(QuillSQLError::NotSupport(format!(
43 "DROP {} is not supported",
44 other
45 ))),
46 },
47 ast::Statement::Query(query) => self.plan_query(query),
48 ast::Statement::Insert {
49 table_name,
50 columns,
51 source,
52 ..
53 } => self.plan_insert(table_name, columns, source),
54 ast::Statement::Update {
55 table,
56 assignments,
57 selection,
58 ..
59 } => self.plan_update(table, assignments, selection),
60 ast::Statement::Delete {
61 tables,
62 from,
63 using,
64 selection,
65 returning,
66 } => {
67 if !tables.is_empty() {
68 return Err(QuillSQLError::Plan(
69 "DELETE with table aliases is not supported".to_string(),
70 ));
71 }
72 if using.is_some() {
73 return Err(QuillSQLError::Plan(
74 "DELETE USING clause is not supported".to_string(),
75 ));
76 }
77 if returning.is_some() {
78 return Err(QuillSQLError::Plan(
79 "DELETE RETURNING is not supported".to_string(),
80 ));
81 }
82 if from.len() != 1 {
83 return Err(QuillSQLError::Plan(
84 "DELETE must target exactly one table".to_string(),
85 ));
86 }
87 self.plan_delete(&from[0], selection)
88 }
89 ast::Statement::Explain { statement, .. } => self.plan_explain(statement),
90 ast::Statement::StartTransaction { modes, .. } => self.plan_begin_transaction(modes),
91 ast::Statement::Commit { .. } => Ok(LogicalPlan::CommitTransaction),
92 ast::Statement::Rollback { .. } => Ok(LogicalPlan::RollbackTransaction),
93 ast::Statement::SetTransaction {
94 modes,
95 snapshot,
96 session,
97 } => self.plan_set_transaction(*session, snapshot, modes),
98 _ => unimplemented!(),
99 }
100 }
101
102 fn plan_begin_transaction(
103 &self,
104 modes: &Vec<ast::TransactionMode>,
105 ) -> QuillSQLResult<LogicalPlan> {
106 Ok(LogicalPlan::BeginTransaction(TransactionModes::from_modes(
107 modes,
108 )))
109 }
110
111 fn plan_set_transaction(
112 &self,
113 session_scope: bool,
114 snapshot: &Option<Value>,
115 modes: &Vec<ast::TransactionMode>,
116 ) -> QuillSQLResult<LogicalPlan> {
117 if snapshot.is_some() {
118 return Err(QuillSQLError::Plan(
119 "SET TRANSACTION SNAPSHOT is not supported".to_string(),
120 ));
121 };
122 let logical_scope = if session_scope {
123 TransactionScope::Session
124 } else {
125 TransactionScope::Transaction
126 };
127 Ok(LogicalPlan::SetTransaction {
128 scope: logical_scope,
129 modes: TransactionModes::from_modes(modes),
130 })
131 }
132
133 pub fn bind_order_by_expr(&self, order_by: &ast::OrderByExpr) -> QuillSQLResult<OrderByExpr> {
134 let expr = self.bind_expr(&order_by.expr)?;
135 Ok(OrderByExpr {
136 expr: Box::new(expr),
137 asc: order_by.asc.unwrap_or(true),
138 nulls_first: order_by.nulls_first.unwrap_or(false),
139 })
140 }
141
142 pub fn bind_table_name(&self, table_name: &ast::ObjectName) -> QuillSQLResult<TableReference> {
143 match table_name.0.as_slice() {
144 [table] => Ok(TableReference::Bare {
145 table: table.value.clone(),
146 }),
147 [schema, table] => Ok(TableReference::Partial {
148 schema: schema.value.clone(),
149 table: table.value.clone(),
150 }),
151 [catalog, schema, table] => Ok(TableReference::Full {
152 catalog: catalog.value.clone(),
153 schema: schema.value.clone(),
154 table: table.value.clone(),
155 }),
156 _ => Err(QuillSQLError::Plan(format!(
157 "Fail to plan table name: {}",
158 table_name
159 ))),
160 }
161 }
162}