From 10e1804612fbf49e84e245871b910c7bac2c1f64 Mon Sep 17 00:00:00 2001 From: Runji Wang Date: Mon, 23 Dec 2024 20:01:44 +0800 Subject: [PATCH] chore: update sqlparser to v53 (#862) Signed-off-by: Runji Wang --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- src/binder/create_function.rs | 39 +++++++++++++++++++++-------------- src/binder/create_table.rs | 15 ++++++++------ src/binder/create_view.rs | 1 + src/binder/delete.rs | 6 +++--- src/binder/expr.rs | 27 +++++++++++++++++------- src/binder/insert.rs | 13 ++++++++---- src/binder/mod.rs | 32 +++++++--------------------- src/binder/select.rs | 15 ++++++++------ src/binder/table.rs | 2 +- src/catalog/root.rs | 7 ++++--- src/db.rs | 4 ++-- 13 files changed, 92 insertions(+), 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 730192bf..095d7095 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2934,9 +2934,9 @@ dependencies = [ [[package]] name = "sqlparser" -version = "0.45.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7bbffee862a796d67959a89859d6b1046bb5016d63e23835ad0da182777bbe0" +checksum = "05a528114c392209b3264855ad491fcce534b94a38771b0a0b97a79379275ce8" dependencies = [ "log", "serde", diff --git a/Cargo.toml b/Cargo.toml index 4e83e4e8..9fe2140e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,7 +66,7 @@ serde = { version = "1", features = ["derive", "rc"] } serde_json = "1" smallvec = { version = "1", features = ["serde"] } sqllogictest = "0.23" -sqlparser = { version = "0.45", features = ["serde"] } +sqlparser = { version = "0.53", features = ["serde"] } thiserror = "2" tikv-jemallocator = { version = "0.6", optional = true, features = [ "disable_initial_exec_tls", diff --git a/src/binder/create_function.rs b/src/binder/create_function.rs index 71cfd2fa..c9fe3c38 100644 --- a/src/binder/create_function.rs +++ b/src/binder/create_function.rs @@ -48,10 +48,14 @@ impl CreateFunction { impl Binder { pub(super) fn bind_create_function( &mut self, - name: ObjectName, - args: Option>, - return_type: Option, - params: CreateFunctionBody, + crate::parser::CreateFunction { + name, + args, + return_type, + function_body, + language, + .. + }: crate::parser::CreateFunction, ) -> Result { let Ok((schema_name, function_name)) = split_name(&name) else { return Err(BindError::BindFunctionError( @@ -70,7 +74,7 @@ impl Binder { let return_type = crate::types::DataType::from(&return_type); // TODO: language check (e.g., currently only support sql) - let Some(language) = params.language.clone() else { + let Some(language) = language else { return Err(BindError::BindFunctionError( "`language` must be specified".to_string(), )); @@ -79,19 +83,22 @@ impl Binder { // SQL udf function supports both single quote (i.e., as 'select $1 + $2') // and double dollar (i.e., as $$select $1 + $2$$) for as clause - let body = match ¶ms.as_ { - Some(FunctionDefinition::SingleQuotedDef(s)) => s.clone(), - Some(FunctionDefinition::DoubleDollarDef(s)) => s.clone(), - None => { - if params.return_.is_none() { - return Err(BindError::BindFunctionError( - "AS or RETURN must be specified".to_string(), - )); - } - // Otherwise this is a return expression + let body = match function_body { + Some(CreateFunctionBody::AsBeforeOptions(expr)) + | Some(CreateFunctionBody::AsAfterOptions(expr)) => match expr { + Expr::Value(Value::SingleQuotedString(s)) => s, + Expr::Value(Value::DollarQuotedString(s)) => s.value, + _ => return Err(BindError::BindFunctionError("expected string".into())), + }, + Some(CreateFunctionBody::Return(return_expr)) => { // Note: this is a current work around, and we are assuming return sql udf // will NOT involve complex syntax, so just reuse the logic for select definition - format!("select {}", ¶ms.return_.unwrap().to_string()) + format!("select {}", &return_expr.to_string()) + } + None => { + return Err(BindError::BindFunctionError( + "AS or RETURN must be specified".to_string(), + )); } }; diff --git a/src/binder/create_table.rs b/src/binder/create_table.rs index 6c86213c..003bcc14 100644 --- a/src/binder/create_table.rs +++ b/src/binder/create_table.rs @@ -50,9 +50,12 @@ impl FromStr for Box { impl Binder { pub(super) fn bind_create_table( &mut self, - name: ObjectName, - columns: &[ColumnDef], - constraints: &[TableConstraint], + crate::parser::CreateTable { + name, + columns, + constraints, + .. + }: crate::parser::CreateTable, ) -> Result { let name = lower_case_name(&name); let (schema_name, table_name) = split_name(&name)?; @@ -66,13 +69,13 @@ impl Binder { // check duplicated column names let mut set = HashSet::new(); - for col in columns { + for col in &columns { if !set.insert(col.name.value.to_lowercase()) { return Err(BindError::ColumnExists(col.name.value.to_lowercase())); } } - let mut ordered_pk_ids = Binder::ordered_pks_from_columns(columns); + let mut ordered_pk_ids = Binder::ordered_pks_from_columns(&columns); let has_pk_from_column = !ordered_pk_ids.is_empty(); if ordered_pk_ids.len() > 1 { @@ -80,7 +83,7 @@ impl Binder { return Err(BindError::NotSupportedTSQL); } - let pks_name_from_constraints = Binder::pks_name_from_constraints(constraints); + let pks_name_from_constraints = Binder::pks_name_from_constraints(&constraints); if has_pk_from_column && !pks_name_from_constraints.is_empty() { // can't get primary key both from "primary key(c1, c2...)" syntax and // column's option diff --git a/src/binder/create_view.rs b/src/binder/create_view.rs index 2b151307..d4e71c64 100644 --- a/src/binder/create_view.rs +++ b/src/binder/create_view.rs @@ -1,5 +1,6 @@ use std::collections::HashSet; +use super::create_table::CreateTable; use super::*; use crate::catalog::{ColumnCatalog, ColumnDesc, ColumnId}; diff --git a/src/binder/delete.rs b/src/binder/delete.rs index 05bba3d2..144ddcd2 100644 --- a/src/binder/delete.rs +++ b/src/binder/delete.rs @@ -3,8 +3,8 @@ use super::*; impl Binder { - pub(super) fn bind_delete(&mut self, from: FromTable, selection: Option) -> Result { - let from = match from { + pub(super) fn bind_delete(&mut self, delete: Delete) -> Result { + let from = match delete.from { FromTable::WithFromKeyword(t) => t, FromTable::WithoutKeyword(t) => t, }; @@ -19,7 +19,7 @@ impl Binder { return Err(BindError::CanNotDelete); } let scan = self.bind_table_def(name, alias.clone(), true)?; - let cond = self.bind_where(selection)?; + let cond = self.bind_where(delete.selection)?; let filter = self.egraph.add(Node::Filter([cond, scan])); Ok(self.egraph.add(Node::Delete([table_id, filter]))) } diff --git a/src/binder/expr.rs b/src/binder/expr.rs index 82c984f1..7bf1a036 100644 --- a/src/binder/expr.rs +++ b/src/binder/expr.rs @@ -56,7 +56,7 @@ impl Binder { high, } => self.bind_between(*expr, negated, *low, *high), Expr::Interval(interval) => self.bind_interval(interval), - Expr::Extract { field, expr } => self.bind_extract(field, *expr), + Expr::Extract { field, expr, .. } => self.bind_extract(field, *expr), Expr::Substring { expr, substring_from, @@ -322,21 +322,35 @@ impl Binder { } fn bind_function(&mut self, func: Function) -> Result { + let mut distinct = false; + let function_args = match &func.args { + FunctionArguments::None => &[], + FunctionArguments::Subquery(_) => { + return Err(BindError::Todo("subquery argument".into())) + } + FunctionArguments::List(arg_list) => { + distinct = arg_list.duplicate_treatment == Some(DuplicateTreatment::Distinct); + arg_list.args.as_slice() + } + }; let mut args = vec![]; - for arg in func.args.clone() { + for arg in function_args { // ignore argument name let arg = match arg { FunctionArg::Named { arg, .. } => arg, + FunctionArg::ExprNamed { arg, .. } => arg, FunctionArg::Unnamed(arg) => arg, }; match arg { - FunctionArgExpr::Expr(expr) => args.push(self.bind_expr(expr)?), + FunctionArgExpr::Expr(expr) => args.push(self.bind_expr(expr.clone())?), FunctionArgExpr::Wildcard => { // No argument in row count args.clear(); break; } - FunctionArgExpr::QualifiedWildcard(_) => todo!("support qualified wildcard"), + FunctionArgExpr::QualifiedWildcard(_) => { + todo!("support qualified wildcard") + } } } @@ -352,8 +366,7 @@ impl Binder { if let Some(ref function_catalog) = catalog.get_function_by_name(schema_name, function_name) { // Create the brand new `udf_context` - let Ok(context) = - UdfContext::create_udf_context(func.args.as_slice(), function_catalog) + let Ok(context) = UdfContext::create_udf_context(function_args, function_catalog) else { return Err(BindError::InvalidExpression( "failed to create udf context".to_string(), @@ -405,7 +418,7 @@ impl Binder { let node = match func.name.to_string().to_lowercase().as_str() { "count" if args.is_empty() => Node::RowCount, - "count" if func.distinct => Node::CountDistinct(args[0]), + "count" if distinct => Node::CountDistinct(args[0]), "count" => Node::Count(args[0]), "max" => Node::Max(args[0]), "min" => Node::Min(args[0]), diff --git a/src/binder/insert.rs b/src/binder/insert.rs index cae147be..fe73a9b4 100644 --- a/src/binder/insert.rs +++ b/src/binder/insert.rs @@ -1,15 +1,20 @@ // Copyright 2024 RisingLight Project Authors. Licensed under Apache-2.0. use super::*; -use crate::parser::Query; impl Binder { pub fn bind_insert( &mut self, - table_name: ObjectName, - columns: Vec, - source: Box, + Insert { + table_name, + columns, + source, + .. + }: Insert, ) -> Result { + let Some(source) = source else { + return Err(BindError::InvalidSQL); + }; let (table, is_internal, is_view) = self.bind_table_id(&table_name)?; if is_internal || is_view { return Err(BindError::CanNotInsert); diff --git a/src/binder/mod.rs b/src/binder/mod.rs index 68daf8d2..67de1eff 100644 --- a/src/binder/mod.rs +++ b/src/binder/mod.rs @@ -25,8 +25,8 @@ mod insert; mod select; mod table; -pub use self::create_function::*; -pub use self::create_table::*; +pub use create_function::CreateFunction; +pub use create_table::CreateTable; pub type Result = std::result::Result; @@ -286,25 +286,16 @@ impl Binder { fn bind_stmt(&mut self, stmt: Statement) -> Result { match stmt { - Statement::CreateTable { - name, - columns, - constraints, - .. - } => self.bind_create_table(name, &columns, &constraints), + Statement::CreateTable(create_table) => self.bind_create_table(create_table), Statement::CreateView { name, columns, query, .. } => self.bind_create_view(name, columns, *query), - Statement::CreateFunction { - name, - args, - return_type, - params, - .. - } => self.bind_create_function(name, args, return_type, params), + Statement::CreateFunction(create_function) => { + self.bind_create_function(create_function) + } Statement::Drop { object_type, if_exists, @@ -312,15 +303,8 @@ impl Binder { cascade, .. } => self.bind_drop(object_type, if_exists, names, cascade), - Statement::Insert { - table_name, - columns, - source: Some(source), - .. - } => self.bind_insert(table_name, columns, source), - Statement::Delete { - from, selection, .. - } => self.bind_delete(from, selection), + Statement::Insert(insert) => self.bind_insert(insert), + Statement::Delete(delete) => self.bind_delete(delete), Statement::Copy { source, to, diff --git a/src/binder/select.rs b/src/binder/select.rs index 3397eb7a..4f1e78f1 100644 --- a/src/binder/select.rs +++ b/src/binder/select.rs @@ -58,7 +58,7 @@ impl Binder { )); } for (column, id) in alias.columns.iter().zip(self.schema(query)) { - columns.insert(column.value.to_lowercase(), id); + columns.insert(column.name.value.to_lowercase(), id); } } else { // `with t` @@ -74,17 +74,20 @@ impl Binder { Ok(query) } - fn bind_select(&mut self, select: Select, order_by: Vec) -> Result { + fn bind_select(&mut self, select: Select, order_by: Option) -> Result { let from = self.bind_from(select.from)?; let projection = self.bind_projection(select.projection, from)?; let mut where_ = self.bind_where(select.selection)?; let groupby = match select.group_by { - GroupByExpr::All => return Err(BindError::Todo("group by all".into())), - GroupByExpr::Expressions(group_by) if group_by.is_empty() => None, - GroupByExpr::Expressions(group_by) => Some(self.bind_groupby(group_by)?), + GroupByExpr::All(_) => return Err(BindError::Todo("group by all".into())), + GroupByExpr::Expressions(exprs, _) if exprs.is_empty() => None, + GroupByExpr::Expressions(exprs, _) => Some(self.bind_groupby(exprs)?), }; let having = self.bind_having(select.having)?; - let orderby = self.bind_orderby(order_by)?; + let orderby = match order_by { + Some(order_by) => self.bind_orderby(order_by.exprs)?, + None => self.egraph.add(Node::List([].into())), + }; let distinct = match select.distinct { None => self.egraph.add(Node::List([].into())), Some(Distinct::Distinct) => projection, diff --git a/src/binder/table.rs b/src/binder/table.rs index bb30761a..b739c85d 100644 --- a/src/binder/table.rs +++ b/src/binder/table.rs @@ -70,7 +70,7 @@ impl Binder { // 'as t(a, b, ..)' let table_name = &alias.name.value; for (column, id) in alias.columns.iter().zip(self.schema(id)) { - self.add_alias(column.value.to_lowercase(), table_name.clone(), id); + self.add_alias(column.name.value.to_lowercase(), table_name.clone(), id); } } else { // move `output_aliases` to current context diff --git a/src/catalog/root.rs b/src/catalog/root.rs index cc9dc7d7..aa4ca642 100644 --- a/src/catalog/root.rs +++ b/src/catalog/root.rs @@ -167,13 +167,14 @@ impl Inner { let stmts = parser::parse(CREATE_SYSTEM_TABLE_SQL).unwrap(); for stmt in stmts { - let parser::Statement::CreateTable { name, columns, .. } = stmt else { + let parser::Statement::CreateTable(create_table) = stmt else { panic!("invalid system table sql: {stmt}"); }; system_schema .add_table( - name.to_string(), - columns + create_table.name.to_string(), + create_table + .columns .into_iter() .enumerate() .map(|(cid, col)| { diff --git a/src/db.rs b/src/db.rs index 181cb4f8..8c4dc422 100644 --- a/src/db.rs +++ b/src/db.rs @@ -173,12 +173,12 @@ impl Database { } } let Statement::SetVariable { - variable, value, .. + variables, value, .. } = stmt else { return Ok(false); }; - let Some(table_name) = variable.0[0].value.strip_prefix("mock_rowcount_") else { + let Some(table_name) = variables[0].0[0].value.strip_prefix("mock_rowcount_") else { return Ok(false); }; let count = value[0]