Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/db/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,12 @@ impl Database {
Ok(None)
}
SqlStatement::Commit => {
self.transaction = None;
self.tables.iter_mut().for_each(|(_, table)| {
table.commit_transaction();
});
if let Some(transaction) = self.transaction.take() {
for transaction_entry in transaction.entries.iter() {
let table = self.get_table_mut(transaction_entry.table_name.as_str())?;
table.commit_transaction(&transaction_entry.affected_rows)?;
}
}
Ok(None)
}
SqlStatement::Rollback(_) => {
Expand Down
19 changes: 13 additions & 6 deletions src/db/table/alter_table/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::interpreter::ast::{AlterTableAction, AlterTableStatement};
pub fn alter_table(database: &mut Database, statement: AlterTableStatement) -> Result<(), String> {
return match statement.action {
AlterTableAction::RenameTable { new_table_name } => {
// TODO: add transaction support to table name changes
let table = database.tables.remove(&statement.table_name);
match table {
Some(table) => database.tables.insert(new_table_name, table),
Expand All @@ -13,6 +14,7 @@ pub fn alter_table(database: &mut Database, statement: AlterTableStatement) -> R
Ok(())
}
AlterTableAction::RenameColumn {
// TODO: add transaction support to column name changes
old_column_name,
new_column_name,
} => {
Expand All @@ -23,7 +25,7 @@ pub fn alter_table(database: &mut Database, statement: AlterTableStatement) -> R
old_column_name, statement.table_name
));
}
table.columns.iter_mut().for_each(|column| {
table.get_columns_mut().iter_mut().for_each(|column| {
if column.name == old_column_name {
column.name = new_column_name.clone();
}
Expand All @@ -38,7 +40,7 @@ pub fn alter_table(database: &mut Database, statement: AlterTableStatement) -> R
column_def.name, statement.table_name
));
}
table.columns.push(column_def);
table.push_column(column_def);
table.get_rows_mut().iter_mut().for_each(|row| {
row.push(Value::Null);
});
Expand Down Expand Up @@ -102,7 +104,7 @@ mod tests {
assert!(
table
.unwrap()
.columns
.get_columns()
.iter()
.any(|column| column.name == "new_name")
);
Expand All @@ -126,7 +128,7 @@ mod tests {
let table = database.get_table("users");
assert!(table.is_ok());
let table = table.unwrap();
assert!(table.columns.last().unwrap().name == "new_column");
assert!(table.get_columns().last().unwrap().name == "new_column");
assert!(table.columns.len() == table[0].len());
assert!(
table
Expand All @@ -150,7 +152,12 @@ mod tests {
let table = database.get_table("users");
assert!(table.is_ok());
let table = table.unwrap();
assert!(!table.columns.iter().any(|column| column.name == "age"));
assert!(
!table
.get_columns()
.iter()
.any(|column| column.name == "age")
);
assert!(table.columns.len() == table[0].len());
let expected_columns_in_order = vec![
ColumnDefinition {
Expand All @@ -169,7 +176,7 @@ mod tests {
constraints: vec![],
},
];
assert_eq!(expected_columns_in_order, table.columns);
assert_eq!(expected_columns_in_order, table.get_columns_clone());
let expected_rows = vec![
Row(vec![
Value::Integer(1),
Expand Down
8 changes: 5 additions & 3 deletions src/db/table/helpers/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ pub fn validate_and_clone_row(table: &Table, row: &Row) -> Result<Row, String> {

let mut row_values: Row = Row(vec![]);
for (i, value) in row.iter().enumerate() {
if value.get_type() != table.columns[i].data_type && value.get_type() != DataType::Null {
if value.get_type() != table.get_columns()[i].data_type
&& value.get_type() != DataType::Null
{
return Err(format!(
"Data type mismatch for column {}",
table.columns[i].name
table.get_columns()[i].name
));
}
row_values.push(row[i].clone());
Expand All @@ -35,7 +37,7 @@ pub fn get_columns_from_row(
let mut row_values: Row = Row(vec![]);

let mut column_values = HashMap::new();
for (i, column) in table.get_columns().into_iter().enumerate() {
for (i, column) in table.get_column_names().into_iter().enumerate() {
if let Some(value) = row.get(i) {
column_values.insert(column, value);
} else {
Expand Down
9 changes: 7 additions & 2 deletions src/db/table/insert/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ pub fn insert(table: &mut Table, statement: InsertIntoStatement) -> Result<Vec<u
// Validate columns
if let Some(columns) = &statement.columns {
for column in columns {
if table.columns.iter().find(|c| c.name == *column).is_none() {
if table
.get_columns()
.iter()
.find(|c| c.name == *column)
.is_none()
{
return Err(format!("Column '{}' does not exist in table", column));
}
}
Expand All @@ -29,7 +34,7 @@ pub fn insert(table: &mut Table, statement: InsertIntoStatement) -> Result<Vec<u
}
for _ in 0..statement.values.len() {
let mut row: Row = Row(vec![]);
for table_column in table.columns.iter() {
for table_column in table.get_columns().iter() {
if map.contains_key(&table_column.name) {
let queue = map.get_mut(&table_column.name).unwrap();
let value = queue.pop_front().unwrap();
Expand Down
91 changes: 68 additions & 23 deletions src/db/table/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,6 @@ pub enum DataType {
Null,
}

#[derive(Debug, PartialEq, Clone)]
pub struct ColumnDefinition {
pub name: String,
pub data_type: DataType,
pub constraints: Vec<ColumnConstraint>,
}

#[derive(Debug, PartialEq, Clone)]
pub struct ColumnConstraint {
pub constraint_type: String,
}

#[derive(Debug, PartialOrd, Clone)]
pub enum Value {
Integer(i64),
Expand Down Expand Up @@ -182,10 +170,35 @@ impl RowStack {
}
}

#[derive(Debug, PartialEq, Clone)]
pub struct ColumnDefinition {
pub name: String,
pub data_type: DataType,
pub constraints: Vec<ColumnConstraint>,
}

#[derive(Debug, PartialEq, Clone)]
pub struct ColumnConstraint {
pub constraint_type: String,
}

#[derive(Debug, PartialEq, Clone)]
pub struct ColumnStack {
pub stack: Vec<ColumnDefinition>,
}

impl ColumnStack {
pub fn new(column: ColumnDefinition) -> Self {
Self {
stack: vec![column],
}
}
}

#[derive(Debug)]
pub struct Table {
pub name: String,
pub columns: Vec<ColumnDefinition>,
columns: Vec<ColumnStack>,
rows: Vec<RowStack>,
}

Expand All @@ -203,13 +216,11 @@ impl IndexMut<usize> for Table {
}
}

// TODO: add swap
// TODO: add pop
impl Table {
pub fn new(name: String, columns: Vec<ColumnDefinition>) -> Self {
Self {
name,
columns,
columns: columns.into_iter().map(|c| ColumnStack::new(c)).collect(),
rows: vec![],
}
}
Expand Down Expand Up @@ -264,8 +275,16 @@ impl Table {
self.rows.pop().and_then(|mut value| value.stack.pop())
}

pub fn commit_transaction(&mut self) {
todo!()
pub fn commit_transaction(&mut self, affected_row_indices: &Vec<usize>) -> Result<(), String> {
// Keep only the top of the each row stack.
for index in affected_row_indices {
if let Some(row_stack) = self.rows.get_mut(*index) {
row_stack.stack = vec![row_stack.stack.last().unwrap().clone()];
} else {
return Err("Error committing transaction. Row stack is empty".to_string());
}
}
Ok(())
}

pub fn rollback_transaction(&mut self) {
Expand All @@ -274,23 +293,23 @@ impl Table {

pub fn get_column_from_row<'a>(&self, row: &'a Vec<Value>, column: &String) -> &'a Value {
for (i, value) in row.iter().enumerate() {
if self.columns[i].name == *column {
if self.get_column_names()[i] == column {
return &value;
}
}
return &Value::Null;
}

pub fn has_column(&self, column: &String) -> bool {
self.columns.iter().any(|c| c.name == *column)
self.get_columns().iter().any(|c| c.name == *column)
}

fn width(&self) -> usize {
self.columns.len()
}

pub fn get_index_of_column(&self, column: &String) -> Result<usize, String> {
for (i, c) in self.columns.iter().enumerate() {
for (i, c) in self.get_columns().iter().enumerate() {
if c.name == *column {
return Ok(i);
}
Expand All @@ -301,7 +320,33 @@ impl Table {
));
}

pub fn get_columns(&self) -> Vec<&String> {
self.columns.iter().map(|column| &column.name).collect()
pub fn get_columns(&self) -> Vec<&ColumnDefinition> {
self.columns
.iter()
.map(|c| c.stack.last().unwrap())
.collect()
}

pub fn get_columns_mut(&mut self) -> Vec<&mut ColumnDefinition> {
self.columns
.iter_mut()
.map(|c| c.stack.last_mut().unwrap())
.collect()
}

pub fn get_column_names(&self) -> Vec<&String> {
self.get_columns()
.iter()
.map(|column| &column.name)
.collect()
}

pub fn push_column(&mut self, column: ColumnDefinition) {
self.columns.push(ColumnStack::new(column));
}

#[cfg(test)]
pub fn get_columns_clone(&self) -> Vec<ColumnDefinition> {
self.get_columns().iter().map(|c| (*c).clone()).collect()
}
}
2 changes: 1 addition & 1 deletion src/db/table/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ fn expand_all_column_names(table: &Table, column_names: &Vec<String>) -> Vec<Str
let mut new = vec![];
for column in column_names {
if *column == "*".to_string() {
for name in table.get_columns() {
for name in table.get_column_names() {
if !column_names.contains(name) {
new.push(name.clone());
}
Expand Down
9 changes: 5 additions & 4 deletions src/db/table/select/select_statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub fn select_statement(table: &Table, statement: &SelectStatement) -> Result<Ve
mod tests {
use super::*;
use crate::db::table::ColumnDefinition;
use crate::db::table::ColumnStack;
use crate::db::table::DataType;
use crate::db::table::test_utils::{assert_table_rows_eq_unordered, default_table};
use crate::db::table::{Row, Value};
Expand Down Expand Up @@ -327,16 +328,16 @@ mod tests {
let mut table = Table {
name: "users".to_string(),
columns: vec![
ColumnDefinition {
ColumnStack::new(ColumnDefinition {
name: "id".to_string(),
data_type: DataType::Integer,
constraints: vec![],
},
ColumnDefinition {
}),
ColumnStack::new(ColumnDefinition {
name: "name".to_string(),
data_type: DataType::Text,
constraints: vec![],
},
}),
],
rows: vec![],
};
Expand Down
Loading
Loading