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
27 changes: 8 additions & 19 deletions src/db/database.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use crate::db::table::{Table, Value};
use crate::interpreter::ast::{SqlStatement, CreateTableStatement, InsertIntoStatement, SelectStatement, DeleteStatement, UpdateStatement, SelectStatementStackElement};
use crate::interpreter::ast::{SqlStatement, CreateTableStatement, InsertIntoStatement, SelectStatementStack, DeleteStatement, UpdateStatement};
use crate::db::table::select;
use crate::db::table::insert;
use crate::db::table::delete;
use crate::db::table::update;
use std::collections::HashMap;

pub struct Database {
tables: HashMap<String, Table>,
pub tables: HashMap<String, Table>,
}

impl Database {
Expand All @@ -27,19 +27,9 @@ impl Database {
self.insert_into_table(statement)?;
Ok(None)
},
SqlStatement::Select(mut statement) => {
let select_statement = statement.elements.pop();
if let Some(select_statement) = select_statement {
match select_statement {
SelectStatementStackElement::SelectStatement(select_statement) => {
let rows = self.select_from_table(select_statement)?;
Ok(Some(rows))
}
_ => Err(format!("Expected select statement, got {:?}", select_statement)),
}
} else {
Ok(None)
}
SqlStatement::Select(statement) => {
let result = self.select_statement_stack(statement)?;
Ok(Some(result))
},
SqlStatement::UpdateStatement(statement) => {
self.update_table(statement)?;
Expand Down Expand Up @@ -67,9 +57,8 @@ impl Database {
Ok(())
}

fn select_from_table(&mut self, statement: SelectStatement) -> Result<Vec<Vec<Value>>, String> {
let table = self.get_table(&statement.table_name)?;
let rows = select::select(table, statement)?;
fn select_statement_stack(&mut self, statement: SelectStatementStack) -> Result<Vec<Vec<Value>>, String> {
let rows = select::select_statement_stack(self, statement)?;
Ok(rows)
}

Expand All @@ -89,7 +78,7 @@ impl Database {
self.tables.contains_key(table_name)
}

fn get_table(&self, table_name: &str) -> Result<&Table, String> {
pub fn get_table(&self, table_name: &str) -> Result<&Table, String> {
if !self.has_table(table_name) {
return Err(format!("Table not found: {}", table_name));
}
Expand Down
2 changes: 1 addition & 1 deletion src/db/table/delete/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::db::table::helpers::common::get_row_indicies_matching_clauses;


pub fn delete(table: &mut Table, statement: DeleteStatement) -> Result<(), String> {
let row_indicies_to_delete = get_row_indicies_matching_clauses(table, statement.where_clause, statement.order_by_clause, statement.limit_clause)?;
let row_indicies_to_delete = get_row_indicies_matching_clauses(table, &statement.where_clause, &statement.order_by_clause, &statement.limit_clause)?;
swap_remove_bulk(table, row_indicies_to_delete)?;
Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions src/db/table/helpers/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub fn get_row_columns_from_indicies(table: &Table, row_indicies: Vec<usize>, co
Ok(rows)
}

pub fn get_row_indicies_matching_where_clause(table: &Table, where_clause: Option<Vec<WhereStackElement>>) -> Result<Vec<usize>, String> {
pub fn get_row_indicies_matching_where_clause(table: &Table, where_clause: &Option<Vec<WhereStackElement>>) -> Result<Vec<usize>, String> {
if let Some(where_clause) = where_clause {
let mut row_indicies: Vec<usize> = vec![];
for (i, row) in table.rows.iter().enumerate() {
Expand Down Expand Up @@ -62,7 +62,7 @@ pub fn get_columns_from_row(table: &Table, row: &Vec<Value>, selected_columns: &
return Ok(row_values);
}

pub fn get_row_indicies_matching_clauses(table: &Table, where_clause: Option<Vec<WhereStackElement>>, order_by_clause: Option<Vec<OrderByClause>>, limit_clause: Option<LimitClause>) -> Result<Vec<usize>, String> {
pub fn get_row_indicies_matching_clauses(table: &Table, where_clause: &Option<Vec<WhereStackElement>>, order_by_clause: &Option<Vec<OrderByClause>>, limit_clause: &Option<LimitClause>) -> Result<Vec<usize>, String> {
let mut row_indicies = get_row_indicies_matching_where_clause(table, where_clause)?;

if let Some(order_by_clause) = order_by_clause {
Expand Down
71 changes: 62 additions & 9 deletions src/db/table/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};

use crate::interpreter::ast::OrderByDirection;

Expand Down Expand Up @@ -32,7 +33,7 @@ pub struct ColumnConstraint {
pub constraint_type: String,
}

#[derive(Debug, PartialEq, PartialOrd, Clone)]
#[derive(Debug, PartialOrd, Clone)]
pub enum Value {
Integer(i64),
Real(f64),
Expand All @@ -59,24 +60,76 @@ impl Value {
(_, Value::Null) => Ordering::Greater,
(Value::Integer(a), Value::Integer(b)) => a.cmp(b),
(Value::Real(a), Value::Real(b)) => {
if a > b {
Ordering::Greater
} else if a < b {
if a.is_nan() && b.is_nan() {
Ordering::Equal
} else if a.is_nan() {
Ordering::Less
} else if b.is_nan() {
Ordering::Greater
} else {
Ordering::Equal
a.partial_cmp(b).unwrap_or(Ordering::Equal)
}

},
(Value::Text(a), Value::Text(b)) => a.cmp(b),
(Value::Blob(a), Value::Blob(b)) => a.cmp(b),
_ => return Ordering::Equal, // Bad - returns equal if data types are different
};

if direction == &OrderByDirection::Asc {
return result;
if direction == &OrderByDirection::Desc {
result.reverse()
} else {
return result.reverse();
result
}
}
}

impl PartialEq for Value {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Value::Integer(a), Value::Integer(b)) => a == b,
(Value::Real(a), Value::Real(b)) => {
if a.is_nan() && b.is_nan() {
true
} else {
a == b
}
},
(Value::Text(a), Value::Text(b)) => a == b,
(Value::Blob(a), Value::Blob(b)) => a == b,
(Value::Null, Value::Null) => true, // Bad - NULL == NULL should be false but this breaks assert_eq!
_ => false,
}
}
}

impl Eq for Value {}

impl Hash for Value {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
Value::Integer(i) => {
0u8.hash(state);
i.hash(state);
}
Value::Real(f) => {
1u8.hash(state);
if f.is_nan() {
u64::MAX.hash(state);
} else {
f.to_bits().hash(state);
}
}
Value::Text(s) => {
2u8.hash(state);
s.hash(state);
}
Value::Blob(b) => {
3u8.hash(state);
b.hash(state);
}
Value::Null => {
4u8.hash(state);
}
}
}
}
Expand Down
Loading
Loading