Skip to content

Commit

Permalink
feat: support more join case
Browse files Browse the repository at this point in the history
- 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`
  • Loading branch information
KKould committed Apr 10, 2024
1 parent 7c0b71f commit 1e80977
Show file tree
Hide file tree
Showing 26 changed files with 693 additions and 503 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,11 @@ implement_from_tuple!(
- User-Defined Function: `features = ["marcos"]`
```rust
function!(TestFunction::test(LogicalType::Integer, LogicalType::Integer) -> LogicalType::Integer => |v1: ValueRef, v2: ValueRef| {
let value = DataValue::binary_op(&v1, &v2, &BinaryOperator::Plus)?;
DataValue::unary_op(&value, &UnaryOperator::Minus)
let plus_binary_evaluator = EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Plus)?;
let value = plus_binary_evaluator.binary_eval(&v1, &v2);

let plus_unary_evaluator = EvaluatorFactory::unary_create(LogicalType::Integer, UnaryOperator::Minus)?;
Ok(plus_unary_evaluator.unary_eval(&value))
});

let fnck_sql = DataBaseBuilder::path("./data")
Expand Down Expand Up @@ -178,7 +181,7 @@ let fnck_sql = DataBaseBuilder::path("./data")
- [x] Alias
- [x] Aggregation: count()/sum()/avg()/min()/max()
- [x] SubQuery[select/from/where]
- [x] Join: Inner/Left/Right/Full/Cross
- [x] Join: Inner/Left/Right/Full/Cross (Natural\Using)
- [x] Group By
- [x] Having
- [x] Order By
Expand Down
2 changes: 1 addition & 1 deletion src/binder/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{

use super::{Binder, QueryBindStep};

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub fn bind_aggregate(
&mut self,
children: LogicalPlan,
Expand Down
2 changes: 1 addition & 1 deletion src/binder/alter_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::planner::operator::Operator;
use crate::planner::LogicalPlan;
use crate::storage::Transaction;

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub(crate) fn bind_alter_table(
&mut self,
name: &ObjectName,
Expand Down
2 changes: 1 addition & 1 deletion src/binder/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::storage::Transaction;
use sqlparser::ast::ObjectName;
use std::sync::Arc;

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

Expand Down
2 changes: 1 addition & 1 deletion src/binder/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl FromStr for ExtSource {
}
}

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub(super) fn bind_copy(
&mut self,
source: CopySource,
Expand Down
2 changes: 1 addition & 1 deletion src/binder/create_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::types::index::IndexType;
use sqlparser::ast::{ObjectName, OrderByExpr};
use std::sync::Arc;

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub(crate) fn bind_create_index(
&mut self,
table_name: &ObjectName,
Expand Down
2 changes: 1 addition & 1 deletion src/binder/create_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::planner::LogicalPlan;
use crate::storage::Transaction;
use crate::types::LogicalType;

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
// TODO: TableConstraint
pub(crate) fn bind_create_table(
&mut self,
Expand Down
2 changes: 1 addition & 1 deletion src/binder/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::storage::Transaction;
use sqlparser::ast::{Expr, TableAlias, TableFactor, TableWithJoins};
use std::sync::Arc;

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub(crate) fn bind_delete(
&mut self,
from: &TableWithJoins,
Expand Down
2 changes: 1 addition & 1 deletion src/binder/describe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::storage::Transaction;
use sqlparser::ast::ObjectName;
use std::sync::Arc;

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub(crate) fn bind_describe(
&mut self,
name: &ObjectName,
Expand Down
2 changes: 1 addition & 1 deletion src/binder/distinct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::planner::operator::aggregate::AggregateOperator;
use crate::planner::LogicalPlan;
use crate::storage::Transaction;

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub fn bind_distinct(
&mut self,
children: LogicalPlan,
Expand Down
2 changes: 1 addition & 1 deletion src/binder/drop_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::storage::Transaction;
use sqlparser::ast::ObjectName;
use std::sync::Arc;

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub(crate) fn bind_drop_table(
&mut self,
name: &ObjectName,
Expand Down
2 changes: 1 addition & 1 deletion src/binder/explain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::planner::operator::Operator;
use crate::planner::LogicalPlan;
use crate::storage::Transaction;

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub(crate) fn bind_explain(&mut self, plan: LogicalPlan) -> Result<LogicalPlan, DatabaseError> {
Ok(LogicalPlan::new(Operator::Explain, vec![plan]))
}
Expand Down
2 changes: 1 addition & 1 deletion src/binder/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ macro_rules! try_default {
};
}

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub(crate) fn bind_expr(&mut self, expr: &Expr) -> Result<ScalarExpression, DatabaseError> {
match expr {
Expr::Identifier(ident) => {
Expand Down
2 changes: 1 addition & 1 deletion src/binder/insert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use sqlparser::ast::{Expr, Ident, ObjectName};
use std::slice;
use std::sync::Arc;

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub(crate) fn bind_insert(
&mut self,
name: &ObjectName,
Expand Down
24 changes: 18 additions & 6 deletions src/binder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,10 @@ impl<'a, T: Transaction> BinderContext<'a, T> {
}

/// get table from bindings
pub fn bind_table(
pub fn bind_table<'b: 'a>(
&self,
table_name: &str,
parent: Option<&'a Binder<'a, T>>,
parent: Option<&'b Binder<'a, 'b, T>>,
) -> Result<&TableCatalog, DatabaseError> {
if let Some(table_catalog) = self.bind_table.iter().find(|((t, alias, _), _)| {
t.as_str() == table_name
Expand Down Expand Up @@ -231,13 +231,13 @@ impl<'a, T: Transaction> BinderContext<'a, T> {
}
}

pub struct Binder<'a, T: Transaction> {
pub struct Binder<'a, 'b, T: Transaction> {
context: BinderContext<'a, T>,
pub(crate) parent: Option<&'a Binder<'a, T>>,
pub(crate) parent: Option<&'b Binder<'a, 'b, T>>,
}

impl<'a, T: Transaction> Binder<'a, T> {
pub fn new(context: BinderContext<'a, T>, parent: Option<&'a Binder<'a, T>>) -> Self {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub fn new(context: BinderContext<'a, T>, parent: Option<&'b Binder<'a, 'b, T>>) -> Self {
Binder { context, parent }
}

Expand Down Expand Up @@ -342,6 +342,18 @@ impl<'a, T: Transaction> Binder<'a, T> {
_ => todo!(),
}
}

fn extend(&mut self, context: BinderContext<'a, T>) {
for (key, table) in context.bind_table {
self.context.bind_table.insert(key, table);
}
for (key, expr) in context.expr_aliases {
self.context.expr_aliases.insert(key, expr);
}
for (key, table_name) in context.table_aliases {
self.context.table_aliases.insert(key, table_name);
}
}
}

fn lower_ident(ident: &Ident) -> String {
Expand Down
23 changes: 17 additions & 6 deletions src/binder/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use sqlparser::ast::{
TableWithJoins,
};

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub(crate) fn bind_query(&mut self, query: &Query) -> Result<LogicalPlan, DatabaseError> {
let origin_step = self.context.step_now();

Expand Down Expand Up @@ -487,7 +487,18 @@ impl<'a, T: Transaction> Binder<'a, T> {
JoinOperator::CrossJoin => (JoinType::Cross, None),
_ => unimplemented!(),
};
let mut right = self.bind_single_table_ref(relation, Some(join_type))?;
let BinderContext {
transaction,
functions,
temp_table_id,
..
} = &self.context;
let mut binder = Binder::new(
BinderContext::new(*transaction, functions, temp_table_id.clone()),
Some(self),
);
let mut right = binder.bind_single_table_ref(relation, Some(join_type))?;
self.extend(binder.context);

let on = match joint_condition {
Some(constraint) => {
Expand Down Expand Up @@ -681,10 +692,10 @@ impl<'a, T: Transaction> Binder<'a, T> {
}
}

fn bind_join_constraint<'b>(
fn bind_join_constraint<'c>(
&mut self,
left_schema: &'b SchemaRef,
right_schema: &'b SchemaRef,
left_schema: &'c SchemaRef,
right_schema: &'c SchemaRef,
constraint: &JoinConstraint,
) -> Result<JoinCondition, DatabaseError> {
match constraint {
Expand Down Expand Up @@ -746,7 +757,7 @@ impl<'a, T: Transaction> Binder<'a, T> {
}
JoinConstraint::None => Ok(JoinCondition::None),
JoinConstraint::Natural => {
let fn_names = |schema: &'b Schema| -> HashSet<&'b str> {
let fn_names = |schema: &'c Schema| -> HashSet<&'c str> {
schema.iter().map(|column| column.name()).collect()
};
let mut on_keys: Vec<(ScalarExpression, ScalarExpression)> = Vec::new();
Expand Down
2 changes: 1 addition & 1 deletion src/binder/show.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::planner::operator::Operator;
use crate::planner::LogicalPlan;
use crate::storage::Transaction;

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub(crate) fn bind_show_tables(&mut self) -> Result<LogicalPlan, DatabaseError> {
Ok(LogicalPlan::new(Operator::Show, vec![]))
}
Expand Down
2 changes: 1 addition & 1 deletion src/binder/truncate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::storage::Transaction;
use sqlparser::ast::ObjectName;
use std::sync::Arc;

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub(crate) fn bind_truncate(
&mut self,
name: &ObjectName,
Expand Down
2 changes: 1 addition & 1 deletion src/binder/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use sqlparser::ast::{Assignment, Expr, TableFactor, TableWithJoins};
use std::slice;
use std::sync::Arc;

impl<'a, T: Transaction> Binder<'a, T> {
impl<'a, 'b, T: Transaction> Binder<'a, 'b, T> {
pub(crate) fn bind_update(
&mut self,
to: &TableWithJoins,
Expand Down
4 changes: 2 additions & 2 deletions src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,10 +310,10 @@ mod test {

function!(TestFunction::test(LogicalType::Integer, LogicalType::Integer) -> LogicalType::Integer => (|v1: ValueRef, v2: ValueRef| {
let plus_binary_evaluator = EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Plus)?;
let value = plus_binary_evaluator.0.binary_eval(&v1, &v2);
let value = plus_binary_evaluator.binary_eval(&v1, &v2);

let plus_unary_evaluator = EvaluatorFactory::unary_create(LogicalType::Integer, UnaryOperator::Minus)?;
Ok(plus_unary_evaluator.0.unary_eval(&value))
Ok(plus_unary_evaluator.unary_eval(&value))
}));

#[tokio::test]
Expand Down
9 changes: 9 additions & 0 deletions src/types/evaluator/boolean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ impl UnaryEvaluator for BooleanNotUnaryEvaluator {
fn unary_eval(&self, value: &DataValue) -> DataValue {
let value = match value {
DataValue::Boolean(value) => value,
DataValue::Null => &None,
_ => unsafe { hint::unreachable_unchecked() },
};
DataValue::Boolean(value.map(|v| !v))
Expand All @@ -29,10 +30,12 @@ impl BinaryEvaluator for BooleanAndBinaryEvaluator {
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
let left = match left {
DataValue::Boolean(value) => value,
DataValue::Null => &None,
_ => unsafe { hint::unreachable_unchecked() },
};
let right = match right {
DataValue::Boolean(value) => value,
DataValue::Null => &None,
_ => unsafe { hint::unreachable_unchecked() },
};
let value = match (left, right) {
Expand All @@ -49,10 +52,12 @@ impl BinaryEvaluator for BooleanOrBinaryEvaluator {
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
let left = match left {
DataValue::Boolean(value) => value,
DataValue::Null => &None,
_ => unsafe { hint::unreachable_unchecked() },
};
let right = match right {
DataValue::Boolean(value) => value,
DataValue::Null => &None,
_ => unsafe { hint::unreachable_unchecked() },
};
let value = match (left, right) {
Expand All @@ -69,10 +74,12 @@ impl BinaryEvaluator for BooleanEqBinaryEvaluator {
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
let left = match left {
DataValue::Boolean(value) => value,
DataValue::Null => &None,
_ => unsafe { hint::unreachable_unchecked() },
};
let right = match right {
DataValue::Boolean(value) => value,
DataValue::Null => &None,
_ => unsafe { hint::unreachable_unchecked() },
};
let value = match (left, right) {
Expand All @@ -88,10 +95,12 @@ impl BinaryEvaluator for BooleanNotEqBinaryEvaluator {
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
let left = match left {
DataValue::Boolean(value) => value,
DataValue::Null => &None,
_ => unsafe { hint::unreachable_unchecked() },
};
let right = match right {
DataValue::Boolean(value) => value,
DataValue::Null => &None,
_ => unsafe { hint::unreachable_unchecked() },
};
let value = match (left, right) {
Expand Down
Loading

0 comments on commit 1e80977

Please sign in to comment.