Skip to content

Commit

Permalink
update sqlparser to v53
Browse files Browse the repository at this point in the history
Signed-off-by: Runji Wang <[email protected]>
  • Loading branch information
wangrunji0408 committed Dec 22, 2024
1 parent fe6ff85 commit cc9eb48
Show file tree
Hide file tree
Showing 13 changed files with 88 additions and 75 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
35 changes: 19 additions & 16 deletions src/binder/create_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,14 @@ impl CreateFunction {
impl Binder {
pub(super) fn bind_create_function(
&mut self,
name: ObjectName,
args: Option<Vec<OperateFunctionArg>>,
return_type: Option<DataType>,
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(
Expand All @@ -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(),
));
Expand All @@ -79,19 +83,18 @@ 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 &params.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)) => expr.to_string(),
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 {}", &params.return_.unwrap().to_string())
format!("select {}", &return_expr.to_string())
}
None => {
return Err(BindError::BindFunctionError(
"AS or RETURN must be specified".to_string(),
));
}
};

Expand Down
15 changes: 9 additions & 6 deletions src/binder/create_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,12 @@ impl FromStr for Box<CreateTable> {
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)?;
Expand All @@ -66,21 +69,21 @@ 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 {
// multi primary key should be declared by "primary key(c1, c2...)" syntax
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
Expand Down
1 change: 1 addition & 0 deletions src/binder/create_view.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::HashSet;

use super::create_table::CreateTable;
use super::*;
use crate::catalog::{ColumnCatalog, ColumnDesc, ColumnId};

Expand Down
6 changes: 3 additions & 3 deletions src/binder/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
use super::*;

impl Binder {
pub(super) fn bind_delete(&mut self, from: FromTable, selection: Option<Expr>) -> 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,
};
Expand All @@ -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])))
}
Expand Down
27 changes: 20 additions & 7 deletions src/binder/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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")
}
}
}

Expand All @@ -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(),
Expand Down Expand Up @@ -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]),
Expand Down
13 changes: 9 additions & 4 deletions src/binder/insert.rs
Original file line number Diff line number Diff line change
@@ -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<Ident>,
source: Box<Query>,
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);
Expand Down
32 changes: 8 additions & 24 deletions src/binder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T = Id> = std::result::Result<T, BindError>;

Expand Down Expand Up @@ -286,41 +286,25 @@ 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,
names,
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,
Expand Down
15 changes: 9 additions & 6 deletions src/binder/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -74,17 +74,20 @@ impl Binder {
Ok(query)
}

fn bind_select(&mut self, select: Select, order_by: Vec<OrderByExpr>) -> Result {
fn bind_select(&mut self, select: Select, order_by: Option<OrderBy>) -> 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,
Expand Down
2 changes: 1 addition & 1 deletion src/binder/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 4 additions & 3 deletions src/catalog/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)| {
Expand Down
4 changes: 2 additions & 2 deletions src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down

0 comments on commit cc9eb48

Please sign in to comment.