diff --git a/src/db/table/core/row.rs b/src/db/table/core/row.rs index 73d8798..f2305a8 100644 --- a/src/db/table/core/row.rs +++ b/src/db/table/core/row.rs @@ -5,7 +5,7 @@ use std::ops::{Deref, DerefMut}; #[repr(transparent)] pub struct Row(pub Vec); -#[derive(Debug)] +#[derive(Debug, PartialEq, Clone)] pub struct RowStack { pub stack: Vec, } @@ -27,4 +27,12 @@ impl RowStack { pub fn new(stack: Row) -> Self { Self { stack: vec![stack] } } + + pub fn new_with_stack(stack: Vec) -> Self { + Self { stack } + } + + pub fn append_clone(&mut self) { + self.stack.push(self.stack.last().unwrap().clone()); + } } diff --git a/src/db/table/core/table.rs b/src/db/table/core/table.rs index 9897b6f..8389f14 100644 --- a/src/db/table/core/table.rs +++ b/src/db/table/core/table.rs @@ -73,6 +73,15 @@ impl Table { .collect() } + pub fn get_row_stacks_mut(&mut self) -> Vec<&mut RowStack> { + self.rows.iter_mut().collect() + } + + #[cfg(test)] + pub fn get_row_stacks_clone(&self) -> Vec { + self.rows.clone() + } + pub fn set_rows(&mut self, rows: Vec) { self.rows = rows.into_iter().map(|r| RowStack::new(r)).collect(); } diff --git a/src/db/table/operations/alter_table/mod.rs b/src/db/table/operations/alter_table/mod.rs index 87b52a2..c0608e0 100644 --- a/src/db/table/operations/alter_table/mod.rs +++ b/src/db/table/operations/alter_table/mod.rs @@ -40,6 +40,11 @@ pub fn alter_table( )); } table.push_column(column_def); + if is_transaction { + table.get_row_stacks_mut().iter_mut().for_each(|row_stack| { + row_stack.append_clone(); + }); + } table.get_rows_mut().iter_mut().for_each(|row| { row.push(Value::Null); }); @@ -59,7 +64,11 @@ pub fn alter_table( .drop_column(&column_name, &table.name, is_transaction)?; // This is kind of bad because it's an O(n^2) operation however SQLite // preserves the order of the columns after drop column statements. - + if is_transaction { + table.get_row_stacks_mut().iter_mut().for_each(|row_stack| { + row_stack.append_clone(); + }); + } table.get_rows_mut().iter_mut().for_each(|row| { row.remove(index); }); @@ -71,7 +80,11 @@ pub fn alter_table( #[cfg(test)] mod tests { use super::*; - use crate::db::table::core::{column::ColumnDefinition, row::Row, value::DataType}; + use crate::db::table::core::{ + column::ColumnDefinition, + row::{Row, RowStack}, + value::DataType, + }; use crate::db::table::test_utils::default_database; #[test] @@ -270,5 +283,57 @@ mod tests { .collect::>()) .collect::>>() ); + + let expected_row_stacks = vec![ + RowStack::new_with_stack(vec![ + Row(vec![ + Value::Integer(1), + Value::Text("John".to_string()), + Value::Integer(25), + Value::Real(1000.0), + ]), + Row(vec![ + Value::Integer(1), + Value::Text("John".to_string()), + Value::Real(1000.0), + ]), + ]), + RowStack::new_with_stack(vec![ + Row(vec![ + Value::Integer(2), + Value::Text("Jane".to_string()), + Value::Integer(30), + Value::Real(2000.0), + ]), + Row(vec![ + Value::Integer(2), + Value::Text("Jane".to_string()), + Value::Real(2000.0), + ]), + ]), + RowStack::new_with_stack(vec![ + Row(vec![ + Value::Integer(3), + Value::Text("Jim".to_string()), + Value::Integer(35), + Value::Real(3000.0), + ]), + Row(vec![ + Value::Integer(3), + Value::Text("Jim".to_string()), + Value::Real(3000.0), + ]), + ]), + RowStack::new_with_stack(vec![ + Row(vec![ + Value::Integer(4), + Value::Null, + Value::Integer(40), + Value::Real(4000.0), + ]), + Row(vec![Value::Integer(4), Value::Null, Value::Real(4000.0)]), + ]), + ]; + assert_eq!(expected_row_stacks, table.get_row_stacks_clone()); } }