Skip to content

Commit

Permalink
Merge branch 'main' into copy
Browse files Browse the repository at this point in the history
  • Loading branch information
loloxwg authored Oct 4, 2023
2 parents 6178e5a + 4bf7385 commit 1ec0726
Show file tree
Hide file tree
Showing 98 changed files with 3,769 additions and 2,423 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ Cargo.lock
/.vscode
/.idea
/.obsidian
.DS_Store
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[package]
name = "kip-sql"
version = "0.0.1-alpha.0"
version = "0.0.1-alpha.3"
edition = "2021"
authors = ["Kould <[email protected]>", "Xwg <[email protected]>"]
description = "build the SQL layer of KipDB database"
Expand Down Expand Up @@ -37,7 +37,7 @@ ahash = "0.8.3"
lazy_static = "1.4.0"
comfy-table = "7.0.1"
bytes = "1.5.0"
kip_db = "0.1.2-alpha.15"
kip_db = "0.1.2-alpha.16"
async-recursion = "1.0.5"
rust_decimal = "1"
csv = "1"
Expand Down
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,33 @@ Storage Support:
![demo](./static/images/demo.png)

### Features
- ORM Mapping
```rust
#[derive(Debug, Clone, Default)]
pub struct Post {
pub post_title: String,
pub post_date: NaiveDateTime,
pub post_body: String,
}

implement_from_tuple!(Post, (
post_title: String => |post: &mut Post, value: DataValue| {
if let Some(title) = value.utf8() {
post.post_title = title;
}
},
post_date: NaiveDateTime => |post: &mut Post, value: DataValue| {
if let Some(date_time) = value.datetime() {
post.post_date = date_time;
}
},
post_body: String => |post: &mut Post, value: DataValue| {
if let Some(body) = value.utf8() {
post.post_body = body;
}
}
));
```
- SQL field options
- not null
- null
Expand Down Expand Up @@ -119,4 +146,4 @@ Storage Support:

### Thanks For
- [Fedomn/sqlrs](https://github.com/Fedomn/sqlrs): 主要参考资料,Optimizer、Executor均参考自sqlrs的设计
- [systemxlabs/tinysql](https://github.com/systemxlabs/tinysql)
- [systemxlabs/bustubx](https://github.com/systemxlabs/bustubx)
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nightly-2023-04-07
nightly-2023-09-29
56 changes: 27 additions & 29 deletions src/binder/aggregate.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
use std::collections::HashSet;
use ahash::RandomState;
use itertools::Itertools;
use sqlparser::ast::{Expr, OrderByExpr};
use std::collections::HashSet;

use crate::{
expression::ScalarExpression,
planner::{
operator::{aggregate::AggregateOperator, sort::SortField},
},
};
use crate::binder::{BindError, InputRefType};
use crate::planner::LogicalPlan;
use crate::storage::Storage;
use crate::{
expression::ScalarExpression,
planner::operator::{aggregate::AggregateOperator, sort::SortField},
};

use super::Binder;

Expand Down Expand Up @@ -40,7 +38,8 @@ impl<S: Storage> Binder<S> {
select_list: &mut [ScalarExpression],
groupby: &[Expr],
) -> Result<(), BindError> {
self.validate_groupby_illegal_column(select_list, groupby).await?;
self.validate_groupby_illegal_column(select_list, groupby)
.await?;

for gb in groupby {
let mut expr = self.bind_expr(gb).await?;
Expand Down Expand Up @@ -89,24 +88,25 @@ impl<S: Storage> Binder<S> {
Ok((return_having, return_orderby))
}

fn visit_column_agg_expr(&mut self, expr: &mut ScalarExpression, is_select: bool) -> Result<(), BindError> {
fn visit_column_agg_expr(
&mut self,
expr: &mut ScalarExpression,
is_select: bool,
) -> Result<(), BindError> {
match expr {
ScalarExpression::AggCall {
ty: return_type, ..
} => {
let ty = return_type.clone();
if is_select {
let index = self.context.input_ref_index(InputRefType::AggCall);
let input_ref = ScalarExpression::InputRef {
index,
ty,
};
let input_ref = ScalarExpression::InputRef { index, ty };
match std::mem::replace(expr, input_ref) {
ScalarExpression::AggCall {
kind,
args,
ty,
distinct
distinct,
} => {
self.context.agg_calls.push(ScalarExpression::AggCall {
distinct,
Expand All @@ -125,14 +125,13 @@ impl<S: Storage> Binder<S> {
.find_position(|agg_expr| agg_expr == &expr)
.ok_or_else(|| BindError::AggMiss(format!("{:?}", expr)))?;

let _ = std::mem::replace(expr, ScalarExpression::InputRef {
index,
ty,
});
let _ = std::mem::replace(expr, ScalarExpression::InputRef { index, ty });
}
}

ScalarExpression::TypeCast { expr, .. } => self.visit_column_agg_expr(expr, is_select)?,
ScalarExpression::TypeCast { expr, .. } => {
self.visit_column_agg_expr(expr, is_select)?
}
ScalarExpression::IsNull { expr } => self.visit_column_agg_expr(expr, is_select)?,
ScalarExpression::Unary { expr, .. } => self.visit_column_agg_expr(expr, is_select)?,
ScalarExpression::Alias { expr, .. } => self.visit_column_agg_expr(expr, is_select)?,
Expand Down Expand Up @@ -185,7 +184,8 @@ impl<S: Storage> Binder<S> {
group_raw_exprs.push(expr);
}
}
let mut group_raw_set: HashSet<&ScalarExpression, RandomState> = HashSet::from_iter(group_raw_exprs.iter());
let mut group_raw_set: HashSet<&ScalarExpression, RandomState> =
HashSet::from_iter(group_raw_exprs.iter());

for expr in select_items {
if expr.has_agg_call(&self.context) {
Expand All @@ -195,19 +195,17 @@ impl<S: Storage> Binder<S> {
group_raw_set.remove(expr);

if !group_raw_exprs.iter().contains(expr) {
return Err(BindError::AggMiss(
format!(
"{:?} must appear in the GROUP BY clause or be used in an aggregate function",
expr
)
));
return Err(BindError::AggMiss(format!(
"{:?} must appear in the GROUP BY clause or be used in an aggregate function",
expr
)));
}
}

if !group_raw_set.is_empty() {
return Err(BindError::AggMiss(
format!("In the GROUP BY clause the field must be in the select clause")
));
return Err(BindError::AggMiss(format!(
"In the GROUP BY clause the field must be in the select clause"
)));
}

Ok(())
Expand Down
40 changes: 20 additions & 20 deletions src/binder/create_table.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use std::collections::HashSet;
use std::sync::Arc;
use itertools::Itertools;
use sqlparser::ast::{ColumnDef, ObjectName, TableConstraint};
use std::collections::HashSet;
use std::sync::Arc;

use super::Binder;
use crate::binder::{BindError, lower_case_name, split_name};
use crate::binder::{lower_case_name, split_name, BindError};
use crate::catalog::ColumnCatalog;
use crate::planner::LogicalPlan;
use crate::planner::operator::create_table::CreateTableOperator;
use crate::planner::operator::Operator;
use crate::planner::LogicalPlan;
use crate::storage::Storage;

impl<S: Storage> Binder<S> {
Expand Down Expand Up @@ -36,24 +36,19 @@ impl<S: Storage> Binder<S> {
.map(|col| ColumnCatalog::from(col.clone()))
.collect_vec();

let primary_key_count = columns
.iter()
.filter(|col| col.desc.is_primary)
.count();
let primary_key_count = columns.iter().filter(|col| col.desc.is_primary).count();

if primary_key_count != 1 {
return Err(BindError::InvalidTable(
"The primary key field must exist and have at least one".to_string()
"The primary key field must exist and have at least one".to_string(),
));
}

let plan = LogicalPlan {
operator: Operator::CreateTable(
CreateTableOperator {
table_name,
columns
}
),
operator: Operator::CreateTable(CreateTableOperator {
table_name,
columns,
}),
childrens: vec![],
};
Ok(plan)
Expand All @@ -62,12 +57,12 @@ impl<S: Storage> Binder<S> {

#[cfg(test)]
mod tests {
use tempfile::TempDir;
use super::*;
use crate::binder::BinderContext;
use crate::catalog::ColumnDesc;
use crate::storage::kip::KipStorage;
use crate::types::LogicalType;
use tempfile::TempDir;

#[tokio::test]
async fn test_create_bind() {
Expand All @@ -84,13 +79,18 @@ mod tests {
assert_eq!(op.table_name, Arc::new("t1".to_string()));
assert_eq!(op.columns[0].name, "id".to_string());
assert_eq!(op.columns[0].nullable, false);
assert_eq!(op.columns[0].desc, ColumnDesc::new(LogicalType::Integer, true, false));
assert_eq!(
op.columns[0].desc,
ColumnDesc::new(LogicalType::Integer, true, false)
);
assert_eq!(op.columns[1].name, "name".to_string());
assert_eq!(op.columns[1].nullable, true);
assert_eq!(op.columns[1].desc, ColumnDesc::new(LogicalType::Varchar(Some(10)), false, false));
assert_eq!(
op.columns[1].desc,
ColumnDesc::new(LogicalType::Varchar(Some(10)), false, false)
);
}
_ => unreachable!()
_ => unreachable!(),
}

}
}
14 changes: 5 additions & 9 deletions src/binder/delete.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use sqlparser::ast::{Expr, TableFactor, TableWithJoins};
use crate::binder::{Binder, BindError, lower_case_name, split_name};
use crate::planner::LogicalPlan;
use crate::binder::{lower_case_name, split_name, BindError, Binder};
use crate::planner::operator::delete::DeleteOperator;
use crate::planner::operator::Operator;
use crate::planner::LogicalPlan;
use crate::storage::Storage;
use sqlparser::ast::{Expr, TableFactor, TableWithJoins};

impl<S: Storage> Binder<S> {
pub(crate) async fn bind_delete(
Expand All @@ -21,15 +21,11 @@ impl<S: Storage> Binder<S> {
}

Ok(LogicalPlan {
operator: Operator::Delete(
DeleteOperator {
table_name
}
),
operator: Operator::Delete(DeleteOperator { table_name }),
childrens: vec![plan],
})
} else {
unreachable!("only table")
}
}
}
}
4 changes: 2 additions & 2 deletions src/binder/distinct.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::binder::Binder;
use crate::expression::ScalarExpression;
use crate::planner::LogicalPlan;
use crate::planner::operator::aggregate::AggregateOperator;
use crate::planner::LogicalPlan;
use crate::storage::Storage;

impl<S: Storage> Binder<S> {
Expand All @@ -12,4 +12,4 @@ impl<S: Storage> Binder<S> {
) -> LogicalPlan {
AggregateOperator::new(children, vec![], select_list)
}
}
}
21 changes: 7 additions & 14 deletions src/binder/drop_table.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
use std::sync::Arc;
use sqlparser::ast::ObjectName;
use crate::binder::{Binder, BindError, lower_case_name, split_name};
use crate::planner::LogicalPlan;
use crate::binder::{lower_case_name, split_name, BindError, Binder};
use crate::planner::operator::drop_table::DropTableOperator;
use crate::planner::operator::Operator;
use crate::planner::LogicalPlan;
use crate::storage::Storage;
use sqlparser::ast::ObjectName;
use std::sync::Arc;

impl<S: Storage> Binder<S> {
pub(crate) fn bind_drop_table(
&mut self,
name: &ObjectName
) -> Result<LogicalPlan, BindError> {
pub(crate) fn bind_drop_table(&mut self, name: &ObjectName) -> Result<LogicalPlan, BindError> {
let name = lower_case_name(&name);
let (_, name) = split_name(&name)?;
let table_name = Arc::new(name.to_string());

let plan = LogicalPlan {
operator: Operator::DropTable(
DropTableOperator {
table_name
}
),
operator: Operator::DropTable(DropTableOperator { table_name }),
childrens: vec![],
};
Ok(plan)
}
}
}
Loading

0 comments on commit 1ec0726

Please sign in to comment.