quill_sql/plan/logical_planner/
plan_query.rs1use crate::error::{QuillSQLError, QuillSQLResult};
2use crate::expression::Expr;
3use crate::utils::scalar::ScalarValue;
4use std::sync::Arc;
5
6use crate::plan::logical_plan::{Limit, LogicalPlan, Sort};
7
8use super::LogicalPlanner;
9
10impl<'a> LogicalPlanner<'a> {
11 pub fn plan_query(&self, query: &sqlparser::ast::Query) -> QuillSQLResult<LogicalPlan> {
12 let plan = self.plan_set_expr(&query.body)?;
13 let plan = self.plan_order_by(plan, &query.order_by)?;
14 self.plan_limit(plan, &query.limit, &query.offset)
15 }
16
17 pub fn plan_order_by(
18 &self,
19 input: LogicalPlan,
20 order_by: &Vec<sqlparser::ast::OrderByExpr>,
21 ) -> QuillSQLResult<LogicalPlan> {
22 if order_by.is_empty() {
23 return Ok(input);
24 }
25
26 let mut order_by_exprs = vec![];
27 for order in order_by {
28 order_by_exprs.push(self.bind_order_by_expr(order)?);
29 }
30
31 Ok(LogicalPlan::Sort(Sort {
32 order_by: order_by_exprs,
33 input: Arc::new(input),
34 limit: None,
35 }))
36 }
37
38 pub fn plan_limit(
39 &self,
40 input: LogicalPlan,
41 limit: &Option<sqlparser::ast::Expr>,
42 offset: &Option<sqlparser::ast::Offset>,
43 ) -> QuillSQLResult<LogicalPlan> {
44 if limit.is_none() && offset.is_none() {
45 return Ok(input);
46 }
47
48 let limit = match limit {
49 None => None,
50 Some(limit_expr) => {
51 let n = match self.bind_expr(limit_expr)? {
52 Expr::Literal(lit) => match lit.value {
53 ScalarValue::Int64(Some(v)) if v >= 0 => Ok(v as usize),
54 _ => Err(QuillSQLError::Plan(format!(
55 "LIMIT must not be negative, {}",
56 lit.value
57 ))),
58 },
59 _ => Err(QuillSQLError::Plan(format!(
60 "LIMIT must be literal, {}",
61 limit_expr
62 ))),
63 }?;
64 Some(n)
65 }
66 };
67
68 let offset = match offset {
69 None => 0,
70 Some(offset_expr) => match self.bind_expr(&offset_expr.value)? {
71 Expr::Literal(lit) => match lit.value {
72 ScalarValue::Int64(Some(v)) => {
73 if v < 0 {
74 return Err(QuillSQLError::Plan(format!("Offset must be >= 0, {}", v)));
75 }
76 Ok(v as usize)
77 }
78 _ => Err(QuillSQLError::Plan(format!(
79 "Offset value not int64, {}",
80 lit.value
81 ))),
82 },
83 _ => Err(QuillSQLError::Plan(format!(
84 "Offset expression not expected, {}",
85 offset_expr
86 ))),
87 }?,
88 };
89
90 Ok(LogicalPlan::Limit(Limit {
91 limit,
92 offset,
93 input: Arc::new(input),
94 }))
95 }
96}