//! QueryBuilder //! //! The QueryBuilder creates sql queries from chained methods use std::any::Any; use std::collections::HashMap; use crate::drivers::DatabaseDriver; #[derive(Debug)] enum QueryClauseType { AndGroupStart, GroupEnd, GroupStart, Like, OrGroupStart, Where, WhereIn, } #[derive(Debug)] struct QueryClause { clause_type: QueryClauseType, conjunction: String, string: String, } #[derive(Default, Debug)] struct QueryState { select_string: String, from_string: String, set_string: String, order_string: String, group_string: String, // Keys for insert/update statement set_array_keys: Vec, // Order by clause order_array: HashMap, // Group by clause group_array: HashMap, // Values to apply to prepared statements values: Vec>, // Values to apply to where clauses in prepared statements where_values: Vec>, limit: u32, offset: u32, // Query components for complex selects query_map: Vec, // Query components for having clauses having_map: Vec, } impl QueryState { pub fn new() -> QueryState { QueryState::default() } } /// The struct representing a query builder #[derive(Default, Debug)] pub struct QueryBuilder { state: QueryState, driver: Option>, } impl QueryBuilder { /// Creates a new QueryBuilder instance pub fn new() -> QueryBuilder { QueryBuilder { state: QueryState::new(), driver: None, } } /// Set the fields to select from the database pub fn select(mut self, fields: &str) -> Self { unimplemented!(); } /// Set a key and value for an insert or update query pub fn set(mut self, key: &str, value: Box) -> Self { // @TODO figure a way to make this easier to use self.state.set_array_keys.push(key.to_string()); self.state.values.push(value); self } /// Set a map of data for an insert or update query pub fn set_batch(mut self, data: HashMap>) -> Self { for (key, value) in data { self = self.set(&key, value); } self } /// Specify the database table to select from pub fn from(mut self, table_name: &str) -> Self { // @TODO properly escape the table name self.state.from_string = table_name.to_string(); self } /// Execute the built query pub fn get(self) -> Box { unimplemented!(); } } #[cfg(test)] mod tests { use super::*; #[test] fn set_key_value() { let builder = QueryBuilder::new() .set("foo", Box::new("bar")); assert!(builder.state.values[0].is::<&str>()); } // fn set_hashmap() { // let qb = QueryBuilder::new(); // // let mut authors = HashMap::new(); // authors.insert( // String::from("Chinua Achebe"), // Box::new("Nigeria")); // authors.insert( // String::from("Rabindranath Tagore"), // Box::new("India")); // authors.insert( // String::from("Anita Nair"), // Box::new("India")); // // let qb = qb.set_batch(authors); // // assert_eq!(qb.state.values.len(), 3); // } }