Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 74 additions & 5 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.53", features = ["serde"] }
sqlparser = { version = "0.59.0", features = ["serde"] }
thiserror = "2"
tikv-jemallocator = { version = "0.6", optional = true, features = [
"disable_initial_exec_tls",
Expand Down
12 changes: 9 additions & 3 deletions src/binder/create_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,14 @@ impl Binder {
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,
Expr::Value(vlaue_with_span) => match vlaue_with_span.value {
Value::SingleQuotedString(s) => s,
Value::DollarQuotedString(s) => s.value,
_ => {
return Err(ErrorKind::BindFunctionError("expected string".into())
.with_spanned(&vlaue_with_span));
}
},
_ => {
return Err(
ErrorKind::BindFunctionError("expected string".into()).with_spanned(&expr)
Expand All @@ -101,7 +107,7 @@ impl Binder {
// will NOT involve complex syntax, so just reuse the logic for select definition
format!("select {}", &return_expr.to_string())
}
None => {
_ => {
return Err(ErrorKind::BindFunctionError(
"AS or RETURN must be specified".to_string(),
)
Expand Down
10 changes: 7 additions & 3 deletions src/binder/create_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ impl FromStr for Box<CreateIndex> {
}

impl Binder {
fn parse_index_type(&self, using: Option<Ident>, with: Vec<Expr>) -> Result<IndexType> {
fn parse_index_type(
&self,
using: Option<sqlparser::ast::IndexType>,
with: Vec<Expr>,
) -> Result<IndexType> {
let Some(using) = using else {
return Err(ErrorKind::InvalidIndex("using clause is required".to_string()).into());
};
Expand Down Expand Up @@ -113,7 +117,7 @@ impl Binder {
ErrorKind::InvalidIndex("invalid with clause".to_string()).into()
);
};
let v: DataValue = v.into();
let v: DataValue = v.value.into();
match key.as_str() {
"distfn" => {
let v = v.as_str();
Expand Down Expand Up @@ -183,7 +187,7 @@ impl Binder {
let mut column_ids = Vec::new();
for column in &columns {
// Ensure column expr is a column reference
let OrderByExpr { expr, .. } = column;
let OrderByExpr { expr, .. } = &column.column;
let Expr::Identifier(column_name) = expr else {
return Err(
ErrorKind::InvalidColumn("column reference expected".to_string())
Expand Down
19 changes: 15 additions & 4 deletions src/binder/create_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl Binder {
return Err(ErrorKind::NotSupportedTSQL.into());
}

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 Expand Up @@ -157,15 +157,26 @@ impl Binder {
}

/// get the primary keys' name sorted by declaration order in "primary key(c1, c2..)" syntax.
fn pks_name_from_constraints(constraints: &[TableConstraint]) -> &[Ident] {
fn pks_name_from_constraints(constraints: &[TableConstraint]) -> Result<&[Ident]> {
for constraint in constraints {
match constraint {
TableConstraint::PrimaryKey { columns, .. } => return columns,
TableConstraint::PrimaryKey { columns, .. } => {
let _ = columns.iter().map(|column_index| {
Ok(match &column_index.column.expr {
Expr::Identifier(ident) => ident,
_ => {
return Err(ErrorKind::InvalidIndex(
column_index.column.expr.to_string(),
));
}
})
});
}
_ => continue,
}
}
// no primary key
&[]
Ok(&[])
}
}

Expand Down
46 changes: 30 additions & 16 deletions src/binder/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ impl Binder {
// parameter-like (i.e., `$1`) values at present
// TODO: consider formally `bind_parameter` in the future
// e.g., lambda function support, etc.
if let Value::Placeholder(key) = &v {
if let Value::Placeholder(key) = &v.value {
self.udf_context
.get_expr(key)
.cloned()
.ok_or_else(|| ErrorKind::InvalidSQL.with_spanned(&v))
} else {
Ok(self.egraph.add(Node::Constant(v.into())))
Ok(self.egraph.add(Node::Constant(v.value.into())))
}
}
Expr::Identifier(ident) => self.bind_ident([ident]),
Expand All @@ -44,7 +44,9 @@ impl Binder {
let isnull = self.bind_is_null(*expr)?;
Ok(self.egraph.add(Node::Not(isnull)))
}
Expr::TypedString { data_type, value } => self.bind_typed_string(data_type, value),
Expr::TypedString(typed_string) => {
self.bind_typed_string(typed_string.data_type, typed_string.value)
}
Expr::Like {
negated,
expr,
Expand All @@ -68,9 +70,9 @@ impl Binder {
Expr::Case {
operand,
conditions,
results,
else_result,
} => self.bind_case(operand, conditions, results, else_result),
..
} => self.bind_case(operand, conditions, else_result),
Expr::InList {
expr,
list,
Expand Down Expand Up @@ -143,8 +145,8 @@ impl Binder {
Or => Node::Or([l, r]),
Xor => Node::Xor([l, r]),
Spaceship => Node::VectorCosineDistance([l, r]),
LtDashGt => Node::VectorL2Distance([l, r]),
Custom(name) => match name.as_str() {
"<->" => Node::VectorL2Distance([l, r]),
"<#>" => Node::VectorNegtiveInnerProduct([l, r]),
op => todo!("bind custom binary op: {:?}", op),
},
Expand All @@ -169,7 +171,7 @@ impl Binder {
// workaround for 'BLOB'
if let DataType::Custom(name, _modifiers) = &ty
&& name.0.len() == 1
&& name.0[0].value.to_lowercase() == "blob"
&& derive_ident(&name.0[0]).value.to_lowercase() == "blob"
{
ty = DataType::Blob(None);
}
Expand All @@ -182,7 +184,11 @@ impl Binder {
Ok(self.egraph.add(Node::IsNull(expr)))
}

fn bind_typed_string(&mut self, data_type: DataType, value: String) -> Result {
fn bind_typed_string(&mut self, data_type: DataType, value_with_span: ValueWithSpan) -> Result {
let ValueWithSpan { value, span } = value_with_span;
let value = value.into_string().ok_or_else(|| {
ErrorKind::InvalidExpression("must be string".to_string()).with_span(span)
})?;
match data_type {
DataType::Date => {
let date = value.parse().map_err(|_| {
Expand Down Expand Up @@ -234,9 +240,18 @@ impl Binder {
}

fn bind_interval(&mut self, interval: parser::Interval) -> Result {
let Expr::Value(Value::Number(v, _) | Value::SingleQuotedString(v)) = *interval.value
else {
panic!("interval value must be number or string");
let Expr::Value(value_with_span) = *interval.value else {
return Err(
ErrorKind::InvalidExpression("interval value must be value".to_string()).into(),
);
};

let ValueWithSpan { value, .. } = value_with_span;

let v = match value {
Value::Number(n, _) => n,
Value::SingleQuotedString(s) => s,
_ => panic!("interval value must be number or string"),
};
let num = v.parse().expect("interval value is not a number");
let value = DataValue::Interval(match interval.leading_field {
Expand All @@ -257,21 +272,20 @@ impl Binder {
fn bind_case(
&mut self,
operand: Option<Box<Expr>>,
conditions: Vec<Expr>,
results: Vec<Expr>,
whens: Vec<CaseWhen>,
else_result: Option<Box<Expr>>,
) -> Result {
let operand = operand.map(|expr| self.bind_expr(*expr)).transpose()?;
let mut case = match else_result {
Some(expr) => self.bind_expr(*expr)?,
None => self.egraph.add(Node::null()),
};
for (cond, result) in conditions.into_iter().rev().zip(results.into_iter().rev()) {
let mut cond = self.bind_expr(cond)?;
for CaseWhen { condition, result } in whens.iter().rev() {
let mut cond = self.bind_expr(condition.clone())?;
if let Some(operand) = operand {
cond = self.egraph.add(Node::Eq([operand, cond]));
}
let mut result = self.bind_expr(result)?;
let mut result = self.bind_expr(result.clone())?;
(result, case) = self.implicit_type_cast(result, case)?;
case = self.egraph.add(Node::If([cond, result, case]));
}
Expand Down
12 changes: 9 additions & 3 deletions src/binder/insert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@ impl Binder {
let Some(source) = insert.source else {
return Err(ErrorKind::InvalidSQL.with_spanned(&insert));
};
let (table, is_internal, is_view) = self.bind_table_id(&insert.table_name)?;
let table_name = match &insert.table {
TableObject::TableName(object_name) => object_name,
TableObject::TableFunction(_) => {
return Err(ErrorKind::Todo("Table Function".into()).with_spanned(&insert.table));
}
};
let (table, is_internal, is_view) = self.bind_table_id(table_name)?;
if is_internal || is_view {
return Err(ErrorKind::CanNotInsert.with_spanned(&insert.table_name));
return Err(ErrorKind::CanNotInsert.with_spanned(table_name));
}
let cols = self.bind_table_columns(&insert.table_name, &insert.columns)?;
let cols = self.bind_table_columns(table_name, &insert.columns)?;
let source = self.bind_query(*source)?.0;
let id = self.egraph.add(Node::Insert([table, cols, source]));
Ok(id)
Expand Down
Loading
Loading