Skip to content

Commit 87f254c

Browse files
authored
impl dml(update) (#50)
* feat: impl dml(update) * docs: add `Bloom` Banner
1 parent 512690f commit 87f254c

18 files changed

Lines changed: 224 additions & 50 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ select * from t1 order by a asc nulls first
4242
- [x] Limit
4343
- DML
4444
- [x] Insert
45-
- [ ] Update
45+
- [x] Update
4646
- [ ] Delete
4747
- DataTypes
4848
- Invalid

src/binder/insert.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ use crate::planner::operator::values::ValuesOperator;
1111
use crate::types::value::ValueRef;
1212

1313
impl Binder {
14-
15-
// TODO: 支持Project
1614
pub(crate) fn bind_insert(
1715
&mut self,
1816
name: ObjectName,
@@ -24,21 +22,21 @@ impl Binder {
2422

2523
if let Some(table) = self.context.catalog.get_table_by_name(table_name) {
2624
let table_id = table.id;
27-
let mut col_catalogs = Vec::new();
25+
let mut columns = Vec::new();
2826

2927
if idents.is_empty() {
30-
col_catalogs = table.all_columns()
28+
columns = table.all_columns()
3129
.into_iter()
3230
.map(|(_, catalog)| catalog.clone())
3331
.collect_vec();
3432
} else {
35-
let bind_table_name = Some(table.name.to_string());
33+
let bind_table_name = Some(table_name.to_string());
3634
for ident in idents {
3735
match self.bind_column_ref_from_identifiers(
3836
slice::from_ref(ident),
3937
bind_table_name.as_ref()
4038
)? {
41-
ScalarExpression::ColumnRef(catalog) => col_catalogs.push(catalog),
39+
ScalarExpression::ColumnRef(catalog) => columns.push(catalog),
4240
_ => unreachable!()
4341
}
4442
}
@@ -56,7 +54,7 @@ impl Binder {
5654
})
5755
.try_collect()?;
5856

59-
let values_plan = self.bind_values(rows, col_catalogs.clone());
57+
let values_plan = self.bind_values(rows, columns);
6058

6159
Ok(LogicalPlan {
6260
operator: Operator::Insert(
@@ -71,15 +69,15 @@ impl Binder {
7169
}
7270
}
7371

74-
fn bind_values(
72+
pub(crate) fn bind_values(
7573
&mut self,
7674
rows: Vec<Vec<ValueRef>>,
77-
col_catalogs: Vec<ColumnRef>
75+
columns: Vec<ColumnRef>
7876
) -> LogicalPlan {
7977
LogicalPlan {
8078
operator: Operator::Values(ValuesOperator {
8179
rows,
82-
columns: col_catalogs,
80+
columns,
8381
}),
8482
childrens: vec![],
8583
}

src/binder/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod create_table;
33
pub mod expr;
44
mod select;
55
mod insert;
6+
mod update;
67

78
use std::collections::BTreeMap;
89
use sqlparser::ast::{Ident, ObjectName, SetExpr, Statement};
@@ -71,6 +72,13 @@ impl Binder {
7172
todo!()
7273
}
7374
}
75+
Statement::Update { table, selection, assignments, .. } => {
76+
if !table.joins.is_empty() {
77+
unimplemented!()
78+
} else {
79+
self.bind_update(table, selection, assignments)?
80+
}
81+
}
7482
_ => unimplemented!(),
7583
};
7684
Ok(plan)

src/binder/select.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl Binder {
108108
Ok(plan)
109109
}
110110

111-
fn bind_table_ref(&mut self, from: &[TableWithJoins]) -> Result<LogicalPlan, BindError> {
111+
pub(crate) fn bind_table_ref(&mut self, from: &[TableWithJoins]) -> Result<LogicalPlan, BindError> {
112112
assert!(from.len() < 2, "not support yet.");
113113
if from.is_empty() {
114114
return Ok(LogicalPlan {
@@ -253,7 +253,7 @@ impl Binder {
253253
Ok(LJoinOperator::new(left, right, on, join_type))
254254
}
255255

256-
fn bind_where(
256+
pub(crate) fn bind_where(
257257
&mut self,
258258
children: LogicalPlan,
259259
predicate: &Expr,

src/binder/update.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
use std::slice;
2+
use sqlparser::ast::{Assignment, Expr, TableFactor, TableWithJoins};
3+
use crate::binder::{Binder, BindError, lower_case_name, split_name};
4+
use crate::expression::ScalarExpression;
5+
use crate::planner::LogicalPlan;
6+
use crate::planner::operator::Operator;
7+
use crate::planner::operator::update::UpdateOperator;
8+
use crate::types::value::ValueRef;
9+
10+
impl Binder {
11+
pub(crate) fn bind_update(
12+
&mut self,
13+
to: &TableWithJoins,
14+
selection: &Option<Expr>,
15+
assignments: &[Assignment]
16+
) -> Result<LogicalPlan, BindError> {
17+
if let TableFactor::Table { name, .. } = &to.relation {
18+
let name = lower_case_name(&name);
19+
let (_, table_name) = split_name(&name)?;
20+
21+
let mut plan = self.bind_table_ref(slice::from_ref(to))?;
22+
23+
if let Some(predicate) = selection {
24+
plan = self.bind_where(plan, predicate)?;
25+
}
26+
27+
if let Some(table) = self.context.catalog.get_table_by_name(table_name) {
28+
let table_id = table.id;
29+
let bind_table_name = Some(table_name.to_string());
30+
31+
let mut columns = Vec::with_capacity(assignments.len());
32+
let mut row = Vec::with_capacity(assignments.len());
33+
34+
35+
for assignment in assignments {
36+
let value = match self.bind_expr(&assignment.value)? {
37+
ScalarExpression::Constant(value) => Ok::<ValueRef, BindError>(value),
38+
_ => unreachable!(),
39+
}?;
40+
41+
for ident in &assignment.id {
42+
match self.bind_column_ref_from_identifiers(
43+
slice::from_ref(&ident),
44+
bind_table_name.as_ref()
45+
)? {
46+
ScalarExpression::ColumnRef(catalog) => {
47+
columns.push(catalog);
48+
row.push(value.clone());
49+
},
50+
_ => unreachable!()
51+
}
52+
}
53+
}
54+
55+
let values_plan = self.bind_values(vec![row], columns);
56+
57+
Ok(LogicalPlan {
58+
operator: Operator::Update(
59+
UpdateOperator {
60+
table_id,
61+
}
62+
),
63+
childrens: vec![plan, values_plan],
64+
})
65+
} else {
66+
Err(BindError::InvalidTable(format!("not found table {}", table_name)))
67+
}
68+
} else {
69+
unreachable!("only table")
70+
}
71+
}
72+
}

src/db.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,13 @@ mod test {
230230
let tuples_full_join = kipsql.run("select * from t1 full join t2 on a = c").await?;
231231
println!("{}", create_table(&tuples_full_join));
232232

233+
println!("update t1 and filter:");
234+
let _ = kipsql.run("update t1 set a = 0 where b > 1").await?;
235+
println!("after t1:");
236+
let update_after_full_t1 = kipsql.run("select * from t1").await?;
237+
println!("{}", create_table(&update_after_full_t1));
238+
239+
233240
Ok(())
234241
})
235242
}

src/execution/executor/dml/insert.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::catalog::CatalogError;
55
use crate::execution::executor::BoxedExecutor;
66
use crate::execution::ExecutorError;
77
use crate::storage::{Storage, Table};
8-
use crate::types::{ColumnId, TableId};
8+
use crate::types::{ColumnId, IdGenerator, TableId};
99
use crate::types::tuple::Tuple;
1010
use crate::types::value::{DataValue, ValueRef};
1111

@@ -29,7 +29,7 @@ impl Insert {
2929
let all_columns = table_catalog.all_columns();
3030

3131
let mut tuple = Tuple {
32-
id: None,
32+
id: Some(IdGenerator::build() as usize),
3333
columns: Vec::with_capacity(all_columns.len()),
3434
values: Vec::with_capacity(all_columns.len()),
3535
};

src/execution/executor/dml/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pub(crate) mod insert;
2+
pub(crate) mod update;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use std::collections::HashMap;
2+
use futures_async_stream::try_stream;
3+
use crate::catalog::CatalogError;
4+
use crate::execution::executor::BoxedExecutor;
5+
use crate::execution::ExecutorError;
6+
use crate::storage::{Storage, Table};
7+
use crate::types::TableId;
8+
use crate::types::tuple::Tuple;
9+
10+
pub struct Update { }
11+
12+
impl Update {
13+
#[try_stream(boxed, ok = Tuple, error = ExecutorError)]
14+
pub async fn execute(table_id: TableId, input: BoxedExecutor, values: BoxedExecutor, storage: impl Storage) {
15+
if let Some(table_catalog) = storage.get_catalog().get_table(&table_id) {
16+
let mut value_map = HashMap::new();
17+
18+
// only once
19+
#[for_await]
20+
for tuple in values {
21+
let Tuple { columns, values, .. } = tuple?;
22+
for i in 0..columns.len() {
23+
value_map.insert(columns[i].id, values[i].clone());
24+
}
25+
}
26+
27+
let table = storage.get_table(&table_catalog.id)?;
28+
29+
#[for_await]
30+
for tuple in input {
31+
let mut tuple = tuple?;
32+
33+
for (i, column) in tuple.columns.iter().enumerate() {
34+
if let Some(value) = value_map.get(&column.id) {
35+
tuple.values[i] = value.clone();
36+
}
37+
}
38+
39+
table.append(tuple)?;
40+
}
41+
} else {
42+
Err(CatalogError::NotFound("root", table_id.to_string()))?;
43+
}
44+
}
45+
}

src/execution/executor/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ use crate::execution::physical_plan::PhysicalPlan;
1414
use crate::execution::executor::ddl::create::CreateTable;
1515
use crate::execution::executor::dql::filter::Filter;
1616
use crate::execution::executor::dml::insert::Insert;
17+
use crate::execution::executor::dml::update::Update;
1718
use crate::execution::executor::dql::join::hash_join::HashJoin;
1819
use crate::execution::executor::dql::limit::Limit;
1920
use crate::execution::executor::dql::projection::Projection;
2021
use crate::execution::executor::dql::seq_scan::SeqScan;
2122
use crate::execution::executor::dql::sort::Sort;
2223
use crate::execution::executor::dql::values::Values;
2324
use crate::execution::ExecutorError;
25+
use crate::execution::physical_plan::physical_update::PhysicalUpdate;
2426
use crate::planner::operator::join::JoinOperator;
2527
use crate::storage::memory::MemStorage;
2628
use crate::types::tuple::Tuple;
@@ -53,6 +55,12 @@ impl Executor {
5355

5456
Insert::execute(table_id, input, self.storage.clone())
5557
}
58+
PhysicalPlan::Update(PhysicalUpdate { table_id, input, values}) => {
59+
let input = self.build(*input);
60+
let values = self.build(*values);
61+
62+
Update::execute(table_id, input, values, self.storage.clone())
63+
}
5664
PhysicalPlan::Values(op) => {
5765
Values::execute(op)
5866
}

0 commit comments

Comments
 (0)