Skip to content

Commit d5070f9

Browse files
authored
Merge pull request #29 from KKould/main
feat(insert): support sql insert simple syntax
2 parents e9ad922 + 24cbc11 commit d5070f9

30 files changed

Lines changed: 424 additions & 485 deletions
Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
use std::collections::HashSet;
2-
32
use anyhow::Result;
43
use sqlparser::ast::{ColumnDef, ObjectName};
54

65
use super::Binder;
76
use crate::binder::{lower_case_name, split_name};
87
use crate::catalog::ColumnCatalog;
98
use crate::planner::logical_create_table_plan::LogicalCreateTablePlan;
9+
use crate::planner::operator::create_table::CreateTableOperator;
1010

1111
impl Binder {
1212
pub(crate) fn bind_create_table(
1313
&mut self,
14-
name: ObjectName,
14+
name: &ObjectName,
1515
columns: &[ColumnDef],
1616
) -> Result<LogicalCreateTablePlan> {
1717
let name = lower_case_name(&name);
18-
1918
let (_, table_name) = split_name(&name)?;
2019

2120
// check duplicated column names
2221
let mut set = HashSet::new();
2322
for col in columns.iter() {
24-
if !set.insert(col.name.value.clone()) {
23+
let col_name = &col.name.value;
24+
if !set.insert(col_name.clone()) {
2525
return Err(anyhow::Error::msg(format!(
2626
"bind duplicated column {}",
27-
col.name.value.clone()
27+
col_name
2828
)));
2929
}
3030
}
@@ -35,8 +35,10 @@ impl Binder {
3535
.collect();
3636

3737
let plan = LogicalCreateTablePlan {
38-
table_name: table_name.to_string(),
39-
columns,
38+
operator: CreateTableOperator {
39+
table_name: table_name.to_string(),
40+
columns
41+
},
4042
};
4143
Ok(plan)
4244
}
@@ -46,7 +48,7 @@ impl Binder {
4648
mod tests {
4749
use super::*;
4850
use crate::binder::BinderContext;
49-
use crate::catalog::{ColumnDesc, RootCatalog};
51+
use crate::catalog::{ColumnCatalog, ColumnDesc, RootCatalog};
5052
use crate::planner::LogicalPlan;
5153
use crate::types::LogicalType;
5254

@@ -58,19 +60,21 @@ mod tests {
5860
let plan1 = binder.bind(&stmt[0]).unwrap();
5961

6062
let plan2 = LogicalPlan::CreateTable(LogicalCreateTablePlan {
61-
table_name: "t1".to_string(),
62-
columns: vec![
63-
ColumnCatalog::new(
64-
"id".to_string(),
65-
false,
66-
ColumnDesc::new(LogicalType::Integer, false)
67-
),
68-
ColumnCatalog::new(
69-
"name".to_string(),
70-
false,
71-
ColumnDesc::new(LogicalType::Varchar, false)
72-
)
73-
],
63+
operator: CreateTableOperator {
64+
table_name: "t1".to_string(),
65+
columns: vec![
66+
ColumnCatalog::new(
67+
"id".to_string(),
68+
false,
69+
ColumnDesc::new(LogicalType::Integer, false)
70+
),
71+
ColumnCatalog::new(
72+
"name".to_string(),
73+
false,
74+
ColumnDesc::new(LogicalType::Varchar, false)
75+
)
76+
],
77+
},
7478
});
7579

7680
assert_eq!(plan1, plan2);

src/binder/insert.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
use std::slice;
2+
use std::sync::Arc;
3+
use sqlparser::ast::{Expr, Ident, ObjectName};
4+
use anyhow::{Error, Result};
5+
use itertools::Itertools;
6+
use crate::binder::{Binder, lower_case_name, split_name};
7+
use crate::catalog::ColumnCatalog;
8+
use crate::expression::ScalarExpression;
9+
use crate::planner::logical_insert_plan::LogicalInsertPlan;
10+
use crate::planner::operator::insert::InsertOperator;
11+
use crate::planner::operator::Operator;
12+
use crate::planner::operator::values::ValuesOperator;
13+
use crate::types::value::DataValue;
14+
15+
impl Binder {
16+
17+
// TODO: 支持Project
18+
// TODO: 检测多行Values对齐
19+
pub(crate) fn bind_insert(
20+
&mut self,
21+
name: ObjectName,
22+
idents: &[Ident],
23+
rows: &Vec<Vec<Expr>>
24+
) -> Result<LogicalInsertPlan> {
25+
let name = lower_case_name(&name);
26+
let (_, table_name) = split_name(&name)?;
27+
28+
if let Some(table) = self.context.catalog.get_table_by_name(table_name) {
29+
let mut col_catalogs = Vec::new();
30+
31+
if idents.is_empty() {
32+
col_catalogs = table.all_columns()
33+
.into_iter()
34+
.map(|(_, catalog)| catalog.clone())
35+
.collect_vec();
36+
} else {
37+
for ident in idents {
38+
match self.bind_column_ref_from_identifiers(slice::from_ref(ident))? {
39+
ScalarExpression::ColumnRef(catalog) => col_catalogs.push(catalog),
40+
_ => unreachable!()
41+
}
42+
}
43+
}
44+
45+
let rows = rows
46+
.into_iter()
47+
.map(|row| {
48+
row.into_iter()
49+
.map(|expr| match self.bind_expr(expr)? {
50+
ScalarExpression::Constant(value) => Ok::<DataValue, Error>(value),
51+
_ => unreachable!(),
52+
})
53+
.try_collect()
54+
})
55+
.try_collect()?;
56+
57+
let values_plan = self.bind_values(rows, col_catalogs.clone());
58+
59+
Ok(LogicalInsertPlan {
60+
operator: Arc::new(
61+
Operator::Insert(
62+
InsertOperator {
63+
table: table_name.to_string(),
64+
}
65+
)
66+
),
67+
children: vec![Arc::new(values_plan)],
68+
})
69+
} else {
70+
Err(anyhow::Error::msg(format!(
71+
"not found table {}",
72+
table_name
73+
)))
74+
}
75+
}
76+
77+
fn bind_values(
78+
&mut self,
79+
rows: Vec<Vec<DataValue>>,
80+
col_catalogs: Vec<ColumnCatalog>
81+
) -> LogicalInsertPlan {
82+
LogicalInsertPlan {
83+
operator: Arc::new(Operator::Values(ValuesOperator {
84+
rows,
85+
col_catalogs,
86+
})),
87+
children: vec![],
88+
}
89+
}
90+
}

src/binder/mod.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
pub mod aggregate;
2-
mod create;
2+
mod create_table;
33
pub mod expr;
44
mod select;
5+
mod insert;
56

67
use std::collections::HashMap;
78

89
use anyhow::Result;
9-
use sqlparser::ast::{Ident, ObjectName, Statement};
10+
use sqlparser::ast::{Ident, ObjectName, SetExpr, Statement};
1011

1112
use crate::catalog::{RootCatalog, DEFAULT_SCHEMA_NAME, CatalogError};
1213
use crate::expression::ScalarExpression;
@@ -65,9 +66,17 @@ impl Binder {
6566
LogicalPlan::Select(plan)
6667
}
6768
Statement::CreateTable { name, columns, .. } => {
68-
let plan = self.bind_create_table(name.to_owned(), &columns)?;
69+
let plan = self.bind_create_table(name, &columns)?;
6970
LogicalPlan::CreateTable(plan)
7071
}
72+
Statement::Insert { table_name, columns, source, .. } => {
73+
if let SetExpr::Values(values) = source.body.as_ref() {
74+
let plan = self.bind_insert(table_name.to_owned(), columns, &values.rows)?;
75+
LogicalPlan::Insert(plan)
76+
} else {
77+
todo!()
78+
}
79+
}
7180
_ => unimplemented!(),
7281
};
7382
Ok(plan)

0 commit comments

Comments
 (0)