Skip to content

Commit b402aa7

Browse files
authored
Remove AlterTable (#129)
* New * Done, just need to implement * Rudamentary impl * Rename table for sled * fix * `cargo fix` & `cargo fmt` * Nearly ready * IndexAdd doesn't need action * fmt * ColumnAdd * Sled ColumnRemove * Fixes & Sled IndexRemove
1 parent 93e5d71 commit b402aa7

File tree

19 files changed

+397
-427
lines changed

19 files changed

+397
-427
lines changed

src/data/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub use {
1111
index::{Index, IndexFilter},
1212
join::{join_iters, JoinType},
1313
row::{Row, RowError},
14-
schema::Schema,
14+
schema::*,
1515
table::{get_name, Table, TableError},
1616
value::*,
1717
};

src/data/schema.rs

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use {
22
crate::{Column, Index},
33
serde::{Deserialize, Serialize},
4+
std::collections::HashMap,
45
};
56

67
#[derive(Clone, Serialize, Deserialize)]
@@ -9,3 +10,175 @@ pub struct Schema {
910
pub column_defs: Vec<Column>,
1011
pub indexes: Vec<Index>,
1112
}
13+
14+
#[derive(Clone, Default)]
15+
pub struct SchemaDiff {
16+
pub table_name: Option<String>,
17+
pub column_defs: Option<HashMap<Option<usize>, Option<Column>>>,
18+
pub indexes: Option<HashMap<Option<usize>, Option<Index>>>,
19+
}
20+
impl SchemaDiff {
21+
pub fn new_rename(new_name: String) -> Self {
22+
Self {
23+
table_name: Some(new_name),
24+
column_defs: None,
25+
indexes: None,
26+
}
27+
}
28+
pub fn new_add_column(new_column: Column) -> Self {
29+
Self {
30+
table_name: None,
31+
column_defs: Some([(None, Some(new_column))].into()),
32+
indexes: None,
33+
}
34+
}
35+
pub fn new_remove_column(column_index: usize) -> Self {
36+
Self {
37+
table_name: None,
38+
column_defs: Some([(Some(column_index), None)].into()),
39+
indexes: None,
40+
}
41+
}
42+
pub fn new_rename_column(
43+
column_index: usize,
44+
mut column: Column,
45+
new_column_name: String,
46+
) -> Self {
47+
column.name = new_column_name;
48+
Self {
49+
table_name: None,
50+
column_defs: Some([(Some(column_index), Some(column))].into()),
51+
indexes: None,
52+
}
53+
}
54+
pub fn new_add_index(new_index: Index) -> Self {
55+
Self {
56+
table_name: None,
57+
column_defs: None,
58+
indexes: Some([(None, Some(new_index))].into()),
59+
}
60+
}
61+
}
62+
63+
impl SchemaDiff {
64+
pub fn merge(self, mut schema: Schema) -> Schema {
65+
if let Some(table_name) = self.table_name {
66+
schema.table_name = table_name
67+
}
68+
if let Some(column_defs) = self.column_defs {
69+
for (index, column_def) in column_defs.into_iter() {
70+
match (index, column_def) {
71+
(None, None) => (),
72+
(Some(index), None) => {
73+
schema.column_defs.remove(index);
74+
} // TODO: WARN: Will be an issue if multiple change
75+
(Some(index), Some(column_def)) => {
76+
schema
77+
.column_defs
78+
.get_mut(index)
79+
.map(|old_column_def| *old_column_def = column_def);
80+
}
81+
(None, Some(column_def)) => {
82+
schema.column_defs.push(column_def);
83+
}
84+
}
85+
}
86+
}
87+
if let Some(indexes) = self.indexes {
88+
for (index, index_def) in indexes.into_iter() {
89+
match (index, index_def) {
90+
(None, None) => (),
91+
(Some(index), None) => {
92+
schema.indexes.remove(index);
93+
} // TODO: WARN: Will be an issue if multiple change
94+
(Some(index), Some(index_def)) => {
95+
schema
96+
.indexes
97+
.get_mut(index)
98+
.map(|old_index_def| *old_index_def = index_def);
99+
}
100+
(None, Some(index_def)) => {
101+
schema.indexes.push(index_def);
102+
}
103+
}
104+
}
105+
}
106+
schema
107+
}
108+
}
109+
110+
impl From<Schema> for SchemaDiff {
111+
fn from(from: Schema) -> Self {
112+
let column_defs = from
113+
.column_defs
114+
.into_iter()
115+
.enumerate()
116+
.map(|(key, col)| (Some(key), Some(col)))
117+
.collect::<HashMap<Option<usize>, Option<Column>>>();
118+
let indexes = from
119+
.indexes
120+
.into_iter()
121+
.enumerate()
122+
.map(|(key, idx)| (Some(key), Some(idx)))
123+
.collect::<HashMap<Option<usize>, Option<Index>>>();
124+
Self {
125+
table_name: Some(from.table_name),
126+
column_defs: Some(column_defs),
127+
indexes: Some(indexes),
128+
}
129+
}
130+
}
131+
132+
pub enum SchemaChange {
133+
RenameTable(String),
134+
135+
ColumnUpdate(usize, Column),
136+
ColumnAdd(Column),
137+
ColumnRemove(usize),
138+
139+
IndexUpdate(usize, Index),
140+
IndexAdd(Index),
141+
IndexRemove(usize),
142+
}
143+
impl SchemaDiff {
144+
pub fn get_changes(&self) -> Vec<SchemaChange> {
145+
use SchemaChange::*;
146+
let mut changes = Vec::new();
147+
if let Some(table_name) = &self.table_name {
148+
changes.push(RenameTable(table_name.clone()))
149+
}
150+
if let Some(column_defs) = &self.column_defs {
151+
for (index, column_def) in column_defs.into_iter() {
152+
match (index, column_def) {
153+
(None, None) => (),
154+
(Some(index), Some(column_def)) => {
155+
changes.push(ColumnUpdate(*index, column_def.clone()));
156+
}
157+
(None, Some(column_def)) => {
158+
changes.push(ColumnAdd(column_def.clone()));
159+
}
160+
(Some(index), None) => {
161+
changes.push(ColumnRemove(*index));
162+
}
163+
}
164+
}
165+
}
166+
if let Some(indexes) = &self.indexes {
167+
for (index, index_def) in indexes.into_iter() {
168+
match (index, index_def) {
169+
(None, None) => (),
170+
(Some(index), Some(index_def)) => {
171+
changes.push(IndexUpdate(*index, index_def.clone()));
172+
}
173+
(None, Some(index_def)) => {
174+
changes.push(IndexAdd(index_def.clone()));
175+
}
176+
(Some(index), None) => {
177+
changes.push(IndexRemove(*index));
178+
}
179+
}
180+
}
181+
}
182+
changes
183+
}
184+
}
Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use {
22
super::{validate, AlterError},
3-
crate::{data::get_name, Error, Glue, Result},
3+
crate::{data::get_name, Error, Glue, Result, SchemaDiff},
44
sqlparser::ast::{AlterTableOperation, ObjectName},
55
};
66

@@ -13,37 +13,65 @@ impl Glue {
1313
let table_name = get_name(name).map_err(Error::from)?;
1414
let database = &mut **self.get_mut_database(&None)?;
1515

16-
match operation {
16+
let diff = match operation {
1717
AlterTableOperation::RenameTable {
1818
table_name: new_table_name,
1919
} => {
2020
let new_table_name = get_name(new_table_name).map_err(Error::from)?;
2121

22-
database.rename_schema(table_name, new_table_name).await
22+
SchemaDiff::new_rename(new_table_name.clone())
2323
}
2424
AlterTableOperation::RenameColumn {
2525
old_column_name,
2626
new_column_name,
2727
} => {
28-
database
29-
.rename_column(table_name, &old_column_name.value, &new_column_name.value)
30-
.await
28+
let schema = database
29+
.fetch_schema(table_name)
30+
.await?
31+
.ok_or(AlterError::TableNotFound(table_name.clone()))?;
32+
let (column_index, column) = schema
33+
.column_defs
34+
.into_iter()
35+
.enumerate()
36+
.find(|(_, column)| column.name == old_column_name.value)
37+
.ok_or(AlterError::ColumnNotFound(
38+
table_name.clone(),
39+
old_column_name.value.clone(),
40+
))?;
41+
SchemaDiff::new_rename_column(column_index, column, new_column_name.value.clone())
3142
}
3243
AlterTableOperation::AddColumn { column_def } => {
3344
validate(column_def).map_err(Error::from)?;
3445

35-
database.add_column(table_name, &column_def.into()).await
46+
SchemaDiff::new_add_column(column_def.into())
3647
}
3748
AlterTableOperation::DropColumn {
3849
column_name,
39-
if_exists,
50+
if_exists: _,
4051
..
4152
} => {
42-
database
43-
.drop_column(table_name, &column_name.value, *if_exists)
44-
.await
53+
let schema = database
54+
.fetch_schema(table_name)
55+
.await?
56+
.ok_or(AlterError::TableNotFound(table_name.clone()))?;
57+
let (column_index, _) = schema
58+
.column_defs
59+
.into_iter()
60+
.enumerate()
61+
.find(|(_, column)| column.name == column_name.value)
62+
.ok_or(AlterError::ColumnNotFound(
63+
table_name.clone(),
64+
column_name.value.clone(),
65+
))?;
66+
67+
SchemaDiff::new_remove_column(column_index)
68+
}
69+
_ => {
70+
return Err(
71+
AlterError::UnsupportedAlterTableOperation(operation.to_string()).into(),
72+
)
4573
}
46-
_ => Err(AlterError::UnsupportedAlterTableOperation(operation.to_string()).into()),
47-
}
74+
};
75+
database.alter_table(table_name, diff).await
4876
}
4977
}

src/executor/alter_table/create_index.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use {
2-
crate::{data::get_name, AlterError, ExecuteError, Glue, Index, Result},
2+
crate::{data::get_name, AlterError, ExecuteError, Glue, Index, Result, SchemaDiff},
33
sqlparser::ast::{Expr, ObjectName, OrderByExpr},
44
};
55

@@ -57,13 +57,14 @@ impl Glue {
5757
)
5858
.into())
5959
} else if let Some(column) = column {
60-
let mut schema = schema.clone();
60+
let schema = schema.clone();
6161
let index = Index::new(name, column, unique);
6262
index
6363
.reset(database, table_name, &schema.column_defs)
6464
.await?;
65-
schema.indexes.push(index);
66-
database.replace_schema(table_name, schema).await
65+
database
66+
.alter_table(table_name, SchemaDiff::new_add_index(index))
67+
.await
6768
} else {
6869
unreachable!()
6970
}

src/result.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ use {
99
thiserror::Error as ThisError,
1010
};
1111

12-
#[cfg(feature = "alter-table")]
13-
use crate::store::AlterTableError;
14-
1512
#[derive(ThisError, Serialize, Debug, PartialEq)]
1613
pub enum WIPError {
1714
#[error("TODO")]
@@ -22,10 +19,6 @@ pub enum WIPError {
2219

2320
#[derive(ThisError, Serialize, Debug)]
2421
pub enum Error {
25-
#[cfg(feature = "alter-table")]
26-
#[error(transparent)]
27-
AlterTable(#[from] AlterTableError),
28-
2922
#[error(transparent)]
3023
#[serde(with = "stringify")]
3124
Storage(#[from] Box<dyn std::error::Error>),
@@ -81,8 +74,6 @@ impl PartialEq for Error {
8174
use Error::*;
8275

8376
match (self, other) {
84-
#[cfg(feature = "alter-table")]
85-
(AlterTable(l), AlterTable(r)) => l == r,
8677
(Execute(l), Execute(r)) => l == r,
8778
(Alter(l), Alter(r)) => l == r,
8879
(Fetch(l), Fetch(r)) => l == r,

src/storages/csv_storage/mod.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,9 @@ mod auto_increment;
22
mod store;
33
mod store_mut;
44
mod utils;
5-
/*mod alter_table;
6-
mod error;
7-
#[cfg(not(feature = "alter-table"))]
8-
impl crate::AlterTable for CSVStorage {}
9-
#[cfg(not(feature = "auto-increment"))]
10-
impl crate::AutoIncrement for CSVStorage {}*/
115

126
use {
13-
crate::{data::Schema, store::*, Column, FullStorage, Result, Storage, ValueType, WIPError},
7+
crate::{data::Schema, Column, FullStorage, Result, Storage, ValueType, WIPError},
148
csv::ReaderBuilder,
159
serde::{Deserialize, Serialize},
1610
std::{
@@ -46,7 +40,6 @@ impl Default for CSVSettings {
4640
}
4741
}
4842

49-
impl AlterTable for CSVStorage {}
5043
impl FullStorage for CSVStorage {}
5144

5245
impl Storage {

src/storages/memory/alter_table.rs

Lines changed: 0 additions & 34 deletions
This file was deleted.

src/storages/memory/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
mod alter_table;
21
mod auto_increment;
32
mod store;
43
mod store_mut;

0 commit comments

Comments
 (0)