quill_sql/plan/logical_planner/
bind_expr.rs1use crate::error::{QuillSQLError, QuillSQLResult};
2use crate::expression::{AggregateFunction, BinaryExpr, ColumnExpr, Expr, Literal};
3use crate::function::AggregateFunctionKind;
4use crate::plan::LogicalPlanner;
5use crate::sql::ast;
6use crate::utils::scalar::ScalarValue;
7use crate::utils::table_ref::TableReference;
8
9impl LogicalPlanner<'_> {
10 pub fn bind_expr(&self, sql: &ast::Expr) -> QuillSQLResult<Expr> {
11 match sql {
12 ast::Expr::Identifier(ident) => Ok(Expr::Column(ColumnExpr {
13 relation: None,
14 name: ident.value.clone(),
15 })),
16 ast::Expr::BinaryOp { left, op, right } => {
17 let left = Box::new(self.bind_expr(left)?);
18 let right = Box::new(self.bind_expr(right)?);
19 Ok(Expr::Binary(BinaryExpr {
20 left,
21 op: op.try_into()?,
22 right,
23 }))
24 }
25 ast::Expr::Value(value) => self.bind_value(value),
26 ast::Expr::CompoundIdentifier(idents) => match idents.as_slice() {
27 [col] => Ok(Expr::Column(ColumnExpr {
28 relation: None,
29 name: col.value.clone(),
30 })),
31 [table, col] => Ok(Expr::Column(ColumnExpr {
32 relation: Some(TableReference::Bare {
33 table: table.value.clone(),
34 }),
35 name: col.value.clone(),
36 })),
37 [schema, table, col] => Ok(Expr::Column(ColumnExpr {
38 relation: Some(TableReference::Partial {
39 schema: schema.value.clone(),
40 table: table.value.clone(),
41 }),
42 name: col.value.clone(),
43 })),
44 [catalog, schema, table, col] => Ok(Expr::Column(ColumnExpr {
45 relation: Some(TableReference::Full {
46 catalog: catalog.value.clone(),
47 schema: schema.value.clone(),
48 table: table.value.clone(),
49 }),
50 name: col.value.clone(),
51 })),
52 _ => Err(QuillSQLError::NotSupport(format!(
53 "sqlparser expr CompoundIdentifier has more than 4 identifiers: {:?}",
54 idents
55 ))),
56 },
57 ast::Expr::Function(function) => self.bind_function(function),
58 _ => Err(QuillSQLError::NotSupport(format!(
59 "sqlparser expr {} not supported",
60 sql
61 ))),
62 }
63 }
64
65 pub fn bind_value(&self, value: &ast::Value) -> QuillSQLResult<Expr> {
66 match value {
67 ast::Value::Number(s, _) => {
68 if let Ok(num) = s.parse::<i64>() {
69 return Ok(Expr::Literal(Literal { value: num.into() }));
70 }
71 if let Ok(num) = s.parse::<f64>() {
72 return Ok(Expr::Literal(Literal { value: num.into() }));
73 }
74 Err(QuillSQLError::Internal(
75 "Failed to parse sql number value".to_string(),
76 ))
77 }
78 ast::Value::Boolean(b) => Ok(Expr::Literal(Literal { value: (*b).into() })),
79 ast::Value::Null => Ok(Expr::Literal(Literal {
80 value: ScalarValue::Int8(None),
81 })),
82 ast::Value::SingleQuotedString(s) => Ok(Expr::Literal(Literal {
83 value: s.clone().into(),
84 })),
85 _ => Err(QuillSQLError::NotSupport(format!(
86 "sqlparser value {} not supported",
87 value
88 ))),
89 }
90 }
91
92 pub fn bind_function(&self, function: &ast::Function) -> QuillSQLResult<Expr> {
93 let name = function.name.to_string();
94
95 if let Some(func_kind) = AggregateFunctionKind::find(name.as_str()) {
96 let args = function
97 .args
98 .iter()
99 .map(|arg| self.bind_function_arg(arg))
100 .collect::<QuillSQLResult<Vec<Expr>>>()?;
101 return Ok(Expr::AggregateFunction(AggregateFunction {
102 func_kind,
103 args,
104 distinct: function.distinct,
105 }));
106 }
107
108 Err(QuillSQLError::Plan(format!(
109 "The function {} is not supported",
110 function
111 )))
112 }
113
114 pub fn bind_function_arg(&self, arg: &ast::FunctionArg) -> QuillSQLResult<Expr> {
115 match arg {
116 ast::FunctionArg::Named {
117 name: _,
118 arg: sqlparser::ast::FunctionArgExpr::Expr(arg),
119 } => self.bind_expr(arg),
120 ast::FunctionArg::Unnamed(sqlparser::ast::FunctionArgExpr::Expr(arg)) => {
121 self.bind_expr(arg)
122 }
123 ast::FunctionArg::Unnamed(sqlparser::ast::FunctionArgExpr::Wildcard) => {
124 Ok(Expr::Literal(Literal { value: 1i64.into() }))
126 }
127 _ => Err(QuillSQLError::Plan(format!(
128 "The function arg {} is not supported",
129 arg
130 ))),
131 }
132 }
133}