diff --git a/default_file.csv b/default_file.csv deleted file mode 100644 index 82c4e67..0000000 --- a/default_file.csv +++ /dev/null @@ -1,11 +0,0 @@ -Nombre,Apellido,Edad,Correo electronico,Profesion -Juan,Perez,32,jperez@gmail.com,medico -Maria,Gomez,28,mgomez@gmail.com,abogado -Carlos,Sánchez,45,csanchez@gmail.com,ingeniero -Ana,Ruiz,36,aruiz@gmail.com,arquitecta -Luis,Martínez,29,lmartinez@gmail.com,profesor -Laura,Domínguez,41,ldominguez@gmail.com,enfermera -Pedro,Fernández,33,pfernandez@gmail.com,diseñador -Lucía,Ramos,26,lramos@gmail.com,psicóloga -Diego,Navarro,39,dnavarro@gmail.com,empresario -Paula,Hernández,31,phernandez@gmail.com,publicista diff --git a/src/conditions/condition.rs b/src/conditions/condition.rs index 0cc9f2d..5dc98b1 100644 --- a/src/conditions/condition.rs +++ b/src/conditions/condition.rs @@ -1,3 +1,5 @@ +use crate::errors::tperrors::Tperrors; + use super::value::Value; /// representation of the condition that can be used on a query @@ -17,12 +19,14 @@ impl Condition { /// /// a query with ```"Name = 'John'"``` will return true /// - pub fn matches_condition(&self, conditions: &str) -> bool { + pub fn matches_condition(&self, conditions: &str) -> Result { let splitted_conditions = conditions.split_whitespace().collect::>(); - /*if (splitted_conditions.len() % 2) == 0 { - return false; // Invalid number of tokens - }*/ + if splitted_conditions.len() <= 1 { + return Err(Tperrors::Syntax( + "Condition should be separated. Example: Name = 'John'".to_string(), + )); + } let mut i = 0; let mut result = true; let mut is_negated = false; // Initialize negation to false @@ -48,7 +52,7 @@ impl Condition { is_negated = false; // Reset negation flag after use if result { // a single true in OR is enough - return true; + return Ok(true); } } _ => { @@ -57,7 +61,7 @@ impl Condition { } } } - result + Ok(result) } /// given a condition, it will evaluate if the condition is met @@ -66,9 +70,9 @@ impl Condition { return false; // Avoid out-of-bounds access } - let column = &conditions[*i].trim_matches('\''); + let column = &conditions[*i].trim_matches('\'').trim_matches('\"'); let operator = &conditions[*i + 1]; - let value = &conditions[*i + 2].trim_matches('\''); + let value = &conditions[*i + 2].trim_matches('\'').trim_matches('\"'); *i += 3; // Advance the index @@ -158,7 +162,7 @@ mod test { ]; for str_condition in str_conditions { - assert_eq!(conditions.matches_condition(str_condition), true); + assert_eq!(conditions.matches_condition(str_condition).unwrap(), true); } } @@ -174,7 +178,7 @@ mod test { let str_conditions = vec!["name = 'John'", "age = 20 OR name = 'John'"]; for str_condition in str_conditions { - assert_eq!(conditions.matches_condition(str_condition), true); + assert_eq!(conditions.matches_condition(str_condition).unwrap(), true); } } @@ -190,7 +194,7 @@ mod test { ]; for str_condition in str_conditions { - assert_ne!(conditions.matches_condition(str_condition), false); + assert_ne!(conditions.matches_condition(str_condition).unwrap(), false); } } @@ -208,7 +212,7 @@ mod test { ]; for str_condition in str_conditions { - assert_eq!(conditions.matches_condition(str_condition), true); + assert_eq!(conditions.matches_condition(str_condition).unwrap(), true); } } } diff --git a/src/consults/delete.rs b/src/consults/delete.rs index cf0fb4f..3f1dce5 100644 --- a/src/consults/delete.rs +++ b/src/consults/delete.rs @@ -1,7 +1,5 @@ -use crate::{ - errors::{fileerrors::FileErrors, tperrors::Tperrors}, - table::Table, -}; +use crate::errors::{fileerrors::FileErrors, tperrors::Tperrors}; +use crate::handler_tables::table::Table; pub struct Delete; @@ -41,19 +39,21 @@ impl Delete { Ok(_) => {} Err(e) => match e { FileErrors::DeletionFailed => { - return Err(Tperrors::Generic("Deletion failed")); + return Err(Tperrors::Generic("Deletion failed".to_string())); } FileErrors::InvalidFile => { - return Err(Tperrors::Generic("Error while updating the file")); + return Err(Tperrors::Generic( + "Error while updating the file".to_string(), + )); } }, } Ok(()) } - Err(_) => { - return Err(Tperrors::Syntax("Invalid columns inside the query")); - } + Err(_) => Err(Tperrors::Syntax( + "Invalid columns inside the query".to_string(), + )), } } } diff --git a/src/consults/insert.rs b/src/consults/insert.rs index 1fd70bd..a22cac8 100644 --- a/src/consults/insert.rs +++ b/src/consults/insert.rs @@ -1,4 +1,5 @@ -use crate::{errors::tperrors::Tperrors, table::Table}; +use crate::errors::tperrors::Tperrors; +use crate::handler_tables::table::*; pub struct Insert; @@ -43,16 +44,12 @@ impl Insert { line.push('\n'); match table.insert_line_to_csv(line) { Ok(_) => Ok(()), - Err(_) => { - return Err(Tperrors::Generic("Error while inserting line")); - } + Err(_) => Err(Tperrors::Generic("Error while inserting line".to_string())), } } - Err(_) => { - return Err(Tperrors::Generic( - "Invalid columns inside the query / mismatch with the table", - )); - } + Err(_) => Err(Tperrors::Generic( + "Invalid columns inside the query / mismatch with the table".to_string(), + )), } } } diff --git a/src/consults/select.rs b/src/consults/select.rs index 501b2a2..cda28fb 100644 --- a/src/consults/select.rs +++ b/src/consults/select.rs @@ -1,5 +1,5 @@ use crate::errors::tperrors::*; -use crate::table::Table; +use crate::handler_tables::table::*; pub struct Select; @@ -52,8 +52,9 @@ impl Select { } Ok(()) } - Err(_) => { - return Err(Tperrors::Syntax("Invalid columns inside the query")); + Err(e) => { + let formatted_error = format!("{}", e); + Err(Tperrors::Generic(formatted_error)) } } } @@ -78,7 +79,7 @@ mod tests { #[test] fn execute_select_fails_with_invalid_columns() { - let mut table = Table::new("./tests/database.csv").unwrap(); + let mut table = Table::new("./tests/test_tables/database.csv".to_string()).unwrap(); let select = Select::new(); // i'm trying to select a column that does not exist let columns = vec!["Trabajo Profesional".to_string()]; diff --git a/src/consults/update.rs b/src/consults/update.rs index b68cf79..66604b7 100644 --- a/src/consults/update.rs +++ b/src/consults/update.rs @@ -1,5 +1,6 @@ use crate::errors::fileerrors::*; -use crate::{errors::tperrors::Tperrors, table::Table}; +use crate::errors::tperrors::Tperrors; +use crate::handler_tables::table::*; pub struct Update; @@ -49,19 +50,21 @@ impl Update { Ok(_) => {} Err(e) => match e { FileErrors::DeletionFailed => { - return Err(Tperrors::Generic("Deletion failed")); + return Err(Tperrors::Generic("Deletion failed".to_string())); } FileErrors::InvalidFile => { - return Err(Tperrors::Generic("Error while updating the file")); + return Err(Tperrors::Generic( + "Error while updating the file".to_string(), + )); } }, } Ok(()) } - Err(_) => { - return Err(Tperrors::Syntax("Invalid columns inside the query")); - } + Err(_) => Err(Tperrors::Syntax( + "Invalid columns inside the query".to_string(), + )), } } } diff --git a/src/errors/tperrors.rs b/src/errors/tperrors.rs index 8122e6a..1f8f232 100644 --- a/src/errors/tperrors.rs +++ b/src/errors/tperrors.rs @@ -1,13 +1,13 @@ use std::fmt::{Display, Formatter, Result}; #[derive(Debug)] -pub enum Tperrors<'a> { - Table(&'a str), - Syntax(&'a str), - Generic(&'a str), +pub enum Tperrors { + Table(String), + Syntax(String), + Generic(String), } -impl<'a> Display for Tperrors<'a> { +impl Display for Tperrors { fn fmt(&self, f: &mut Formatter<'_>) -> Result { match self { Tperrors::Generic(e) => write!(f, "ERROR {}", e), diff --git a/src/extractors/extractor.rs b/src/extractors/extractor.rs index 2fbe183..53e18ef 100644 --- a/src/extractors/extractor.rs +++ b/src/extractors/extractor.rs @@ -18,10 +18,7 @@ impl Extractor { /// Example /// SELECT name, age FROM table; /// Returns ["name", "age"] - pub fn extract_columns_for_select( - &self, - query: &str, - ) -> Result, Tperrors<'static>> { + pub fn extract_columns_for_select(&self, query: &str) -> Result, Tperrors> { let query = query.trim(); let where_pos = query.find("FROM"); @@ -42,9 +39,9 @@ impl Extractor { Ok(columns) } - None => { - return Err(Tperrors::Syntax("Invalid select query (Missing FROM)")); - } + None => Err(Tperrors::Syntax( + "Invalid select query (Missing FROM)".to_string(), + )), } } @@ -58,18 +55,22 @@ impl Extractor { pub fn extract_columns_and_values_for_insert( &self, query: &str, - ) -> Result<(Vec, Vec), Tperrors<'static>> { + ) -> Result<(Vec, Vec), Tperrors> { let (start_columns, end_columns) = match (query.find("("), query.find(")")) { (Some(start), Some(end)) => (start, end), _ => { - return Err(Tperrors::Syntax("Invalid INSERT query (Missing columns)")); + return Err(Tperrors::Syntax( + "Invalid INSERT query (Missing columns)".to_string(), + )); } }; let (start_values, end_values) = match (query.rfind("("), query.rfind(")")) { (Some(start), Some(end)) => (start, end), _ => { - return Err(Tperrors::Syntax("Invalid INSERT query (Missing values)")); + return Err(Tperrors::Syntax( + "Invalid INSERT query (Missing values)".to_string(), + )); } }; @@ -97,7 +98,7 @@ impl Extractor { // if len doesnt match we return an error if columns.len() != values.len() { return Err(Tperrors::Syntax( - "Invalid INSERT query (Columns and values do not match)", + "Invalid INSERT query (Columns and values do not match)".to_string(), )); } @@ -117,13 +118,13 @@ impl Extractor { pub fn extract_columns_and_values_for_update( &self, query: &str, - ) -> Result<(Vec, Vec), Tperrors<'static>> { + ) -> Result<(Vec, Vec), Tperrors> { let (start_columns, end_columns) = match (query.find("SET"), query.find("WHERE")) { (Some(start), Some(end)) => (start, end), (Some(start), None) => (start, query.len() - 1), // no WHERE, it means ALL tables.., risky.. _ => { return Err(Tperrors::Syntax( - "Invalid UPDATE query (Missing SET or WHERE)", + "Invalid UPDATE query (Missing SET or WHERE)".to_string(), )); } }; @@ -144,7 +145,9 @@ impl Extractor { let what_to_update = what_to_update.split('=').collect::>(); if what_to_update.len() != 2 { - return Err(Tperrors::Syntax("Invalid UPDATE query (Missing =)")); + return Err(Tperrors::Syntax( + "Invalid UPDATE query (Missing =)".to_string(), + )); } let column = what_to_update[0].trim().to_string(); @@ -167,17 +170,15 @@ impl Extractor { &self, query: &'a str, consult: SQLCommand, - ) -> Result<&'a str, Tperrors<'static>> { + ) -> Result<&'a str, Tperrors> { let query = query.trim(); let (start, offset, end) = self.extract_positions(query, consult); match (start, end) { - (0, 0) => { - return Err(Tperrors::Syntax( - "Invalid query (Missing any KEY words on your consult)", - )); - } + (0, 0) => Err(Tperrors::Syntax( + "Invalid query (Missing any KEY words on your consult)".to_string(), + )), _ => { let table_data = &query[start + offset..end]; let table_data = table_data.trim(); diff --git a/src/lib.rs b/src/lib.rs index 505fcfd..facb968 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,4 +2,4 @@ pub mod conditions; pub mod consults; pub mod errors; pub mod extractors; -pub mod table; +pub mod handler_tables; diff --git a/src/main.rs b/src/main.rs index a6ccf1a..7a47bf0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,9 +2,11 @@ use tp_individual::{ consults::{delete::Delete, insert::Insert, select::Select, update::Update}, errors::tperrors::Tperrors, extractors::{extractor::Extractor, sqlcommand::SQLCommand}, - table::Table, + handler_tables::folder_tables::FolderTables, }; +use tp_individual::handler_tables::table::Table; + fn main() { // lets read the args let args: Vec = std::env::args().collect(); @@ -24,53 +26,21 @@ fn valid_number_of_args(args: &usize) -> bool { true } -/// This function checks if the table selected in the query is the same as the table that is being used -fn check_valid_table( - extractor: &Extractor, - table: &Table, - consult: &str, - method: SQLCommand, -) -> Result<(), Tperrors<'static>> { - match extractor.extract_table(consult, method) { - Ok(table_name_from_query) => { - let table_name = match table.get_file_name() { - Ok(table_name) => table_name, - Err(e) => { - return Err(e); - } - }; - - if table_name_from_query != table_name { - return Err(Tperrors::Table("Invalid table selected")); - } - } - Err(e) => { - return Err(e); - } - }; - Ok(()) -} /// Executes the main logical problem of the program -fn run(args: Vec) -> Result<(), Tperrors<'static>> { +fn run(args: Vec) -> Result<(), Tperrors> { if !valid_number_of_args(&args.len()) { // we stop the program, invalid number of arguments - return Err(Tperrors::Generic("Invalid number of arguments")); + return Err(Tperrors::Generic("Invalid number of arguments".to_string())); } // Now, we have the arguments... let file = &args[1]; let consult = &args[2].trim(); - let opening_table = Table::new(file); - - let mut table = match opening_table { - Ok(table) => table, - Err(_) => { - return Err(Tperrors::Table( - "Error opening the table - The selected table is invalid", - )); - } - }; + let folder_tables = FolderTables::new(file).unwrap_or_else(|e| { + eprintln!("{}", e); + std::process::exit(1); + }); let splitted_consult = consult.split(" ").collect::>(); let command = splitted_consult[0]; @@ -81,138 +51,184 @@ fn run(args: Vec) -> Result<(), Tperrors<'static>> { "SELECT" => { let select = Select; - if !select.is_valid_query(consult) { - return Err(Tperrors::Syntax( - "Invalid select query (Missing either SELECT , FROM or ;)", - )); - } - - // checking if its a valid table - match check_valid_table(&extractor, &table, consult, SQLCommand::Select) { + match resolve_select(&extractor, folder_tables, consult, select) { Ok(_) => {} Err(e) => { return Err(e); } }; - - // lets get the columns selected from the query - let columns = match extractor.extract_columns_for_select(consult) { - Ok(columns) => columns, - Err(e) => { - return Err(e); - } - }; - - // Conditions of the query (if they exists) - let conditions = extractor.extract_as_str_conditions(consult); - - // Sorting method (if existst) - let sorting_vector = match extractor.extract_orderby_as_str(consult) { - Some(sorting) => { - let vec_sort = extractor.parser_orderby_from_str_to_vec(sorting); - Some(vec_sort) - } - None => None, - }; - - // lets execute the query - let result = select.execute_select(&mut table, columns, conditions, sorting_vector); - - if result.is_err() { - return Err(Tperrors::Syntax("Invalid columns inside the query")); - } - - return Ok(()); } "INSERT" => { let insert = Insert; - if !insert.is_valid_query(consult) { - return Err(Tperrors::Syntax( - "Invalid insert query (Missing either INSERT INTO, VALUES or ;)", - )); - } - - match check_valid_table(&extractor, &table, consult, SQLCommand::Insert) { + match resolve_insert(&extractor, folder_tables, consult, insert) { Ok(_) => {} Err(e) => { return Err(e); } }; - - let (columns, values) = match extractor.extract_columns_and_values_for_insert(consult) { - Ok((columns, values)) => (columns, values), - Err(e) => { - return Err(e); - } - }; - let result = insert.execute_insert(&mut table, columns, values); - - if result.is_err() { - return Err(Tperrors::Syntax("Invalid columns inside the query")); - } - - return Ok(()); } "UPDATE" => { let update = Update; - if !update.is_valid_query(consult) { - return Err(Tperrors::Syntax( - "Invalid update query (Missing either UPDATE, SET, WHERE or ;)", - )); - } - - match check_valid_table(&extractor, &table, consult, SQLCommand::Update) { + match resolve_update(&extractor, folder_tables, consult, update) { Ok(_) => {} Err(e) => { return Err(e); } }; + } + "DELETE" => { + let delete = Delete; - let (columns, values) = match extractor.extract_columns_and_values_for_update(consult) { - Ok((columns, values)) => (columns, values), + match resolve_delete(&extractor, folder_tables, consult, delete) { + Ok(_) => {} Err(e) => { return Err(e); } }; + } + _ => { + return Err(Tperrors::Syntax("Invalid command".to_string())); + } + } + Ok(()) +} - let conditions = extractor.extract_as_str_conditions(consult); +/// Given a consult, command a folder_table instance +/// +/// Returns a Table instance to work with +/// +/// If the table is not found, returns an error +fn return_proper_table_to_work_with( + extractor: &Extractor, + folder_tables: FolderTables, + consult: &str, + command: SQLCommand, +) -> Result { + let extracted_table_name = match extractor.extract_table(consult, command) { + Ok(table_name) => table_name, + Err(e) => { + return Err(e); + } + }; - let result = update.execute_update(&mut table, columns, values, conditions); + let table: Table = match folder_tables.get_path(extracted_table_name) { + Some(table_path) => Table::new(table_path).unwrap_or_else(|e| { + eprintln!("{}", e); + std::process::exit(1); + }), - if result.is_err() { - return Err(Tperrors::Syntax("Invalid columns inside the query")); - } + None => { + return Err(Tperrors::Table("Table not found in the folder".to_string())); } - "DELETE" => { - let delete = Delete; + }; + + Ok(table) +} +fn resolve_select( + extractor: &Extractor, + folder_tables: FolderTables, + consult: &str, + select: Select, +) -> Result<(), Tperrors> { + let mut table = + return_proper_table_to_work_with(extractor, folder_tables, consult, SQLCommand::Select)?; + + if !select.is_valid_query(consult) { + return Err(Tperrors::Syntax( + "Invalid select query (Missing either SELECT , FROM or ;)".to_string(), + )); + } - if !delete.is_valid_query(consult) { - return Err(Tperrors::Syntax( - "Invalid delete query (Missing either DELETE, FROM or ;)", - )); - } + // lets get the columns selected from the query + let columns = match extractor.extract_columns_for_select(consult) { + Ok(columns) => columns, + Err(e) => { + return Err(e); + } + }; - // checking if its a valid table - match check_valid_table(&extractor, &table, consult, SQLCommand::Delete) { - Ok(_) => {} - Err(e) => { - return Err(e); - } - }; + // Conditions of the query (if they exists) + let conditions = extractor.extract_as_str_conditions(consult); + + // Sorting method (if existst) + let sorting_vector = match extractor.extract_orderby_as_str(consult) { + Some(sorting) => { + let vec_sort = extractor.parser_orderby_from_str_to_vec(sorting); + Some(vec_sort) + } + None => None, + }; - let conditions = extractor.extract_as_str_conditions(consult); + // lets execute the query + select.execute_select(&mut table, columns, conditions, sorting_vector) +} - let result = delete.execute_delete(&mut table, conditions); +fn resolve_insert( + extractor: &Extractor, + folder_tables: FolderTables, + consult: &str, + insert: Insert, +) -> Result<(), Tperrors> { + let mut table = + return_proper_table_to_work_with(extractor, folder_tables, consult, SQLCommand::Insert)?; + if !insert.is_valid_query(consult) { + return Err(Tperrors::Syntax( + "Invalid insert query (Missing either INSERT INTO, VALUES or ;)".to_string(), + )); + } - if result.is_err() { - return Err(Tperrors::Generic("Something happened with the deletion")); - } + let (columns, values) = match extractor.extract_columns_and_values_for_insert(consult) { + Ok((columns, values)) => (columns, values), + Err(e) => { + return Err(e); } - _ => { - return Err(Tperrors::Syntax("Invalid command")); + }; + insert.execute_insert(&mut table, columns, values) +} + +fn resolve_update( + extractor: &Extractor, + folder_tables: FolderTables, + consult: &str, + update: Update, +) -> Result<(), Tperrors> { + let mut table = + return_proper_table_to_work_with(extractor, folder_tables, consult, SQLCommand::Update)?; + if !update.is_valid_query(consult) { + return Err(Tperrors::Syntax( + "Invalid update query (Missing either UPDATE, SET, WHERE or ;)".to_string(), + )); + } + + let (columns, values) = match extractor.extract_columns_and_values_for_update(consult) { + Ok((columns, values)) => (columns, values), + Err(e) => { + return Err(e); } + }; + + let conditions = extractor.extract_as_str_conditions(consult); + + update.execute_update(&mut table, columns, values, conditions) +} + +fn resolve_delete( + extractor: &Extractor, + folder_tables: FolderTables, + consult: &str, + delete: Delete, +) -> Result<(), Tperrors> { + let mut table = + return_proper_table_to_work_with(extractor, folder_tables, consult, SQLCommand::Delete)?; + if !delete.is_valid_query(consult) { + return Err(Tperrors::Syntax( + "Invalid delete query (Missing either DELETE, FROM, WHERE or ;)".to_string(), + )); } - Ok(()) + + let conditions = extractor.extract_as_str_conditions(consult); + + delete.execute_delete(&mut table, conditions) } diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 0d2557b..934e9fc 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -10,7 +10,7 @@ use process::Command; #[test] fn integration_select_query() { let route_file = format!("./tests/select_query_{}.csv", std::process::id()); - let argument = format!("cargo run -- ./tests/database.csv \"SELECT Nombre, Edad FROM database WHERE Edad >= 33;\" > {}", route_file); + let argument = format!("cargo run -- ./tests/test_tables \"SELECT Nombre, Edad FROM database WHERE Edad >= 33;\" > {}", route_file); let mut command = Command::new("sh") // Use "cmd" for Windows .arg("-c") // Execute a shell command .arg(argument) @@ -62,15 +62,15 @@ fn integration_insert_query() { let _ = File::create(&route_file).unwrap(); // lets clone the file - fs::copy("./tests/database.csv", &route_file).unwrap(); + fs::copy("./tests/test_tables/database.csv", &route_file).unwrap(); let table_name_start = route_file.rfind("/").unwrap() + 1; let table_name_end = route_file.rfind(".").unwrap(); let table_name = &route_file[table_name_start..table_name_end]; let argument = format!( - "cargo run -- {} \"INSERT INTO {} (Nombre, Edad) VALUES ('Juan', 20);\"", - route_file, table_name + "cargo run -- ./tests \"INSERT INTO {} (Nombre, Edad) VALUES ('Juan', 20);\"", + table_name ); let mut command = Command::new("sh") // Use "cmd" for Windows @@ -102,15 +102,15 @@ fn integration_update_query() { let _ = File::create(&route_file).unwrap(); // lets clone the file - fs::copy("./tests/database.csv", &route_file).unwrap(); + fs::copy("./tests/test_tables/database.csv", &route_file).unwrap(); let table_name_start = route_file.rfind("/").unwrap() + 1; let table_name_end = route_file.rfind(".").unwrap(); let table_name = &route_file[table_name_start..table_name_end]; let argument = format!( - "cargo run -- {} \"UPDATE {} SET Nombre = 'TEST', Edad = 45 WHERE Edad = 31;\"", - route_file, table_name + "cargo run -- ./tests \"UPDATE {} SET Nombre = 'TEST', Edad = 45 WHERE Edad = 31;\"", + table_name ); let mut command = Command::new("sh") // Use "cmd" for Windows @@ -142,16 +142,13 @@ fn integration_delete_query() { let _ = File::create(&route_file).unwrap(); // lets clone the file - fs::copy("./tests/database.csv", &route_file).unwrap(); + fs::copy("./tests/test_tables/database.csv", &route_file).unwrap(); let table_name_start = route_file.rfind("/").unwrap() + 1; let table_name_end = route_file.rfind(".").unwrap(); let table_name = &route_file[table_name_start..table_name_end]; - let argument = format!( - "cargo run -- {} \"DELETE FROM {};\"", - route_file, table_name - ); + let argument = format!("cargo run -- ./tests \"DELETE FROM {};\"", table_name); let mut command = Command::new("sh") // Use "cmd" for Windows .arg("-c") // Execute a shell command diff --git a/tests/database.csv b/tests/test_tables/database.csv similarity index 100% rename from tests/database.csv rename to tests/test_tables/database.csv