Skip to content

Commit eac3ae8

Browse files
authored
feat: support more join case (KipData#204)
* feat: support more join case - reconstruct the alias mechanism to ensure correctness during Join - support Natural Join - support multiple from(to Cross Join) - when Using and Natural Join, the same columns are automatically removed (Fixme: JoinType needs to be supported to decide whether to use the columns of the left table or the right table) - `RangeDetacher::detach` removes meaningless `Result` * feat: support more join case - fix: `UnaryEvaluator` & `BinaryEvaluator` handle the situation when the data is Null - fix: use an independent Binder when joining and the parent binder can extend context(from subquery join) - feat: add `Mod` for `BinaryEvaluator` * fix: lifetime on select.rs * style: codefmt
1 parent 74ea950 commit eac3ae8

32 files changed

+1605
-214
lines changed

Diff for: README.md

+6-3
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,11 @@ implement_from_tuple!(
114114
- User-Defined Function: `features = ["marcos"]`
115115
```rust
116116
function!(TestFunction::test(LogicalType::Integer, LogicalType::Integer) -> LogicalType::Integer => |v1: ValueRef, v2: ValueRef| {
117-
let value = DataValue::binary_op(&v1, &v2, &BinaryOperator::Plus)?;
118-
DataValue::unary_op(&value, &UnaryOperator::Minus)
117+
let plus_binary_evaluator = EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Plus)?;
118+
let value = plus_binary_evaluator.binary_eval(&v1, &v2);
119+
120+
let plus_unary_evaluator = EvaluatorFactory::unary_create(LogicalType::Integer, UnaryOperator::Minus)?;
121+
Ok(plus_unary_evaluator.unary_eval(&value))
119122
});
120123

121124
let fnck_sql = DataBaseBuilder::path("./data")
@@ -178,7 +181,7 @@ let fnck_sql = DataBaseBuilder::path("./data")
178181
- [x] Alias
179182
- [x] Aggregation: count()/sum()/avg()/min()/max()
180183
- [x] SubQuery[select/from/where]
181-
- [x] Join: Inner/Left/Right/Full/Cross
184+
- [x] Join: Inner/Left/Right/Full/Cross (Natural\Using)
182185
- [x] Group By
183186
- [x] Having
184187
- [x] Order By

Diff for: src/binder/aggregate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::{
1414

1515
use super::{Binder, QueryBindStep};
1616

17-
impl<'a, T: Transaction> Binder<'a, T> {
17+
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
1818
pub fn bind_aggregate(
1919
&mut self,
2020
children: LogicalPlan,

Diff for: src/binder/alter_table.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::planner::operator::Operator;
1212
use crate::planner::LogicalPlan;
1313
use crate::storage::Transaction;
1414

15-
impl<'a, T: Transaction> Binder<'a, T> {
15+
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
1616
pub(crate) fn bind_alter_table(
1717
&mut self,
1818
name: &ObjectName,

Diff for: src/binder/analyze.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ use crate::storage::Transaction;
88
use sqlparser::ast::ObjectName;
99
use std::sync::Arc;
1010

11-
impl<'a, T: Transaction> Binder<'a, T> {
11+
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
1212
pub(crate) fn bind_analyze(&mut self, name: &ObjectName) -> Result<LogicalPlan, DatabaseError> {
1313
let table_name = Arc::new(lower_case_name(name)?);
1414

15-
let table_catalog = self.context.table_and_bind(table_name.clone(), None)?;
15+
let table_catalog = self
16+
.context
17+
.table_and_bind(table_name.clone(), None, None)?;
1618
let index_metas = table_catalog.indexes.clone();
1719

1820
let scan_op = ScanOperator::build(table_name.clone(), table_catalog);

Diff for: src/binder/copy.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl FromStr for ExtSource {
5151
}
5252
}
5353

54-
impl<'a, T: Transaction> Binder<'a, T> {
54+
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
5555
pub(super) fn bind_copy(
5656
&mut self,
5757
source: CopySource,

Diff for: src/binder/create_index.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::types::index::IndexType;
1010
use sqlparser::ast::{ObjectName, OrderByExpr};
1111
use std::sync::Arc;
1212

13-
impl<'a, T: Transaction> Binder<'a, T> {
13+
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
1414
pub(crate) fn bind_create_index(
1515
&mut self,
1616
table_name: &ObjectName,
@@ -29,7 +29,9 @@ impl<'a, T: Transaction> Binder<'a, T> {
2929
IndexType::Composite
3030
};
3131

32-
let table = self.context.table_and_bind(table_name.clone(), None)?;
32+
let table = self
33+
.context
34+
.table_and_bind(table_name.clone(), None, None)?;
3335
let plan = ScanOperator::build(table_name.clone(), table);
3436
let mut columns = Vec::with_capacity(exprs.len());
3537

Diff for: src/binder/create_table.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::planner::LogicalPlan;
1414
use crate::storage::Transaction;
1515
use crate::types::LogicalType;
1616

17-
impl<'a, T: Transaction> Binder<'a, T> {
17+
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
1818
// TODO: TableConstraint
1919
pub(crate) fn bind_create_table(
2020
&mut self,

Diff for: src/binder/delete.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,37 @@ use crate::planner::operator::scan::ScanOperator;
55
use crate::planner::operator::Operator;
66
use crate::planner::LogicalPlan;
77
use crate::storage::Transaction;
8-
use sqlparser::ast::{Expr, TableFactor, TableWithJoins};
8+
use sqlparser::ast::{Expr, TableAlias, TableFactor, TableWithJoins};
99
use std::sync::Arc;
1010

11-
impl<'a, T: Transaction> Binder<'a, T> {
11+
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
1212
pub(crate) fn bind_delete(
1313
&mut self,
1414
from: &TableWithJoins,
1515
selection: &Option<Expr>,
1616
) -> Result<LogicalPlan, DatabaseError> {
1717
if let TableFactor::Table { name, alias, .. } = &from.relation {
1818
let table_name = Arc::new(lower_case_name(name)?);
19+
let mut table_alias = None;
20+
let mut alias_idents = None;
1921

20-
let table_catalog = self.context.table_and_bind(table_name.clone(), None)?;
22+
if let Some(TableAlias { name, columns }) = alias {
23+
table_alias = Some(Arc::new(name.value.to_lowercase()));
24+
alias_idents = Some(columns);
25+
}
26+
let table_catalog =
27+
self.context
28+
.table_and_bind(table_name.clone(), table_alias.clone(), None)?;
2129
let primary_key_column = table_catalog
2230
.columns()
2331
.find(|column| column.desc.is_primary)
2432
.cloned()
2533
.unwrap();
2634
let mut plan = ScanOperator::build(table_name.clone(), table_catalog);
2735

28-
if let Some(alias) = alias {
29-
self.context
30-
.add_table_alias(alias.to_string(), table_name.clone());
36+
if let Some(alias_idents) = alias_idents {
37+
plan =
38+
self.bind_alias(plan, alias_idents, table_alias.unwrap(), table_name.clone())?;
3139
}
3240

3341
if let Some(predicate) = selection {

Diff for: src/binder/describe.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::storage::Transaction;
77
use sqlparser::ast::ObjectName;
88
use std::sync::Arc;
99

10-
impl<'a, T: Transaction> Binder<'a, T> {
10+
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
1111
pub(crate) fn bind_describe(
1212
&mut self,
1313
name: &ObjectName,

Diff for: src/binder/distinct.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::planner::operator::aggregate::AggregateOperator;
44
use crate::planner::LogicalPlan;
55
use crate::storage::Transaction;
66

7-
impl<'a, T: Transaction> Binder<'a, T> {
7+
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
88
pub fn bind_distinct(
99
&mut self,
1010
children: LogicalPlan,

Diff for: src/binder/drop_table.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::storage::Transaction;
77
use sqlparser::ast::ObjectName;
88
use std::sync::Arc;
99

10-
impl<'a, T: Transaction> Binder<'a, T> {
10+
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
1111
pub(crate) fn bind_drop_table(
1212
&mut self,
1313
name: &ObjectName,

Diff for: src/binder/explain.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::planner::operator::Operator;
44
use crate::planner::LogicalPlan;
55
use crate::storage::Transaction;
66

7-
impl<'a, T: Transaction> Binder<'a, T> {
7+
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
88
pub(crate) fn bind_explain(&mut self, plan: LogicalPlan) -> Result<LogicalPlan, DatabaseError> {
99
Ok(LogicalPlan::new(Operator::Explain, vec![plan]))
1010
}

Diff for: src/binder/expr.rs

+30-17
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ use crate::types::value::{DataValue, Utf8Type};
1919
use crate::types::LogicalType;
2020

2121
macro_rules! try_alias {
22-
($context:expr, $column_name:expr) => {
23-
if let Some(expr) = $context.expr_aliases.get(&$column_name) {
22+
($context:expr, $full_name:expr) => {
23+
if let Some(expr) = $context.expr_aliases.get(&$full_name) {
2424
return Ok(ScalarExpression::Alias {
2525
expr: Box::new(expr.clone()),
26-
alias: AliasType::Name($column_name),
26+
alias: AliasType::Name($full_name.1),
2727
});
2828
}
2929
};
@@ -37,7 +37,7 @@ macro_rules! try_default {
3737
};
3838
}
3939

40-
impl<'a, T: Transaction> Binder<'a, T> {
40+
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
4141
pub(crate) fn bind_expr(&mut self, expr: &Expr) -> Result<ScalarExpression, DatabaseError> {
4242
match expr {
4343
Expr::Identifier(ident) => {
@@ -283,7 +283,7 @@ impl<'a, T: Transaction> Binder<'a, T> {
283283
idents: &[Ident],
284284
bind_table_name: Option<String>,
285285
) -> Result<ScalarExpression, DatabaseError> {
286-
let (table_name, column_name) = match idents {
286+
let full_name = match idents {
287287
[column] => (None, lower_ident(column)),
288288
[table, column] => (Some(lower_ident(table)), lower_ident(column)),
289289
_ => {
@@ -296,25 +296,40 @@ impl<'a, T: Transaction> Binder<'a, T> {
296296
))
297297
}
298298
};
299-
try_alias!(self.context, column_name);
299+
try_alias!(self.context, full_name);
300300
if self.context.allow_default {
301-
try_default!(&table_name, column_name);
301+
try_default!(&full_name.0, full_name.1);
302302
}
303-
if let Some(table) = table_name.or(bind_table_name) {
303+
if let Some(table) = full_name.0.or(bind_table_name) {
304304
let table_catalog = self.context.bind_table(&table, self.parent)?;
305305

306306
let column_catalog = table_catalog
307-
.get_column_by_name(&column_name)
308-
.ok_or_else(|| DatabaseError::NotFound("column", column_name))?;
307+
.get_column_by_name(&full_name.1)
308+
.ok_or_else(|| DatabaseError::NotFound("column", full_name.1))?;
309309
Ok(ScalarExpression::ColumnRef(column_catalog.clone()))
310310
} else {
311-
let op = |got_column: &mut Option<&'a ColumnRef>, context: &BinderContext<'a, T>| {
312-
for table_catalog in context.bind_table.values() {
311+
let op = |got_column: &mut Option<ScalarExpression>, context: &BinderContext<'a, T>| {
312+
for ((_, alias, _), table_catalog) in context.bind_table.iter() {
313313
if got_column.is_some() {
314314
break;
315315
}
316-
if let Some(column_catalog) = table_catalog.get_column_by_name(&column_name) {
317-
*got_column = Some(column_catalog);
316+
if let Some(alias) = alias {
317+
*got_column = self.context.expr_aliases.iter().find_map(
318+
|((alias_table, alias_column), expr)| {
319+
matches!(
320+
alias_table
321+
.as_ref()
322+
.map(|table_name| table_name == alias.as_ref()
323+
&& alias_column == &full_name.1),
324+
Some(true)
325+
)
326+
.then(|| expr.clone())
327+
},
328+
);
329+
} else if let Some(column_catalog) =
330+
table_catalog.get_column_by_name(&full_name.1)
331+
{
332+
*got_column = Some(ScalarExpression::ColumnRef(column_catalog.clone()));
318333
}
319334
}
320335
};
@@ -325,9 +340,7 @@ impl<'a, T: Transaction> Binder<'a, T> {
325340
if let Some(parent) = self.parent {
326341
op(&mut got_column, &parent.context);
327342
}
328-
let column_catalog =
329-
got_column.ok_or_else(|| DatabaseError::NotFound("column", column_name))?;
330-
Ok(ScalarExpression::ColumnRef(column_catalog.clone()))
343+
Ok(got_column.ok_or_else(|| DatabaseError::NotFound("column", full_name.1))?)
331344
}
332345
}
333346

Diff for: src/binder/insert.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use sqlparser::ast::{Expr, Ident, ObjectName};
1212
use std::slice;
1313
use std::sync::Arc;
1414

15-
impl<'a, T: Transaction> Binder<'a, T> {
15+
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
1616
pub(crate) fn bind_insert(
1717
&mut self,
1818
name: &ObjectName,
@@ -24,7 +24,9 @@ impl<'a, T: Transaction> Binder<'a, T> {
2424
self.context.allow_default = true;
2525
let table_name = Arc::new(lower_case_name(name)?);
2626

27-
let table = self.context.table_and_bind(table_name.clone(), None)?;
27+
let table = self
28+
.context
29+
.table_and_bind(table_name.clone(), None, None)?;
2830
let mut _schema_ref = None;
2931
let values_len = expr_rows[0].len();
3032

0 commit comments

Comments
 (0)