2019-04-02 16:35:52 -04:00
|
|
|
//! QueryBuilder
|
|
|
|
//!
|
|
|
|
//! The QueryBuilder creates sql queries from chained methods
|
2019-04-02 17:23:52 -04:00
|
|
|
use std::any::Any;
|
2019-04-02 14:36:11 -04:00
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
use crate::drivers::DatabaseDriver;
|
|
|
|
|
2019-04-03 13:29:08 -04:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum LikeWildcard {
|
|
|
|
Before,
|
|
|
|
After,
|
|
|
|
Both,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum JoinType {
|
|
|
|
Inner,
|
|
|
|
Outer,
|
|
|
|
Left,
|
|
|
|
Right,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum OrderDirection {
|
|
|
|
Asc,
|
|
|
|
Desc,
|
|
|
|
}
|
|
|
|
|
2019-04-02 14:36:11 -04:00
|
|
|
#[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
|
2019-04-02 17:23:52 -04:00
|
|
|
set_array_keys: Vec<String>,
|
2019-04-02 14:36:11 -04:00
|
|
|
|
|
|
|
// Order by clause
|
|
|
|
order_array: HashMap<String, String>,
|
|
|
|
|
|
|
|
// Group by clause
|
|
|
|
group_array: HashMap<String, String>,
|
|
|
|
|
|
|
|
// Values to apply to prepared statements
|
2019-04-02 17:23:52 -04:00
|
|
|
values: Vec<Box<dyn Any>>,
|
2019-04-02 14:36:11 -04:00
|
|
|
|
|
|
|
// Values to apply to where clauses in prepared statements
|
2019-04-02 17:23:52 -04:00
|
|
|
where_values: Vec<Box<dyn Any>>,
|
2019-04-02 14:36:11 -04:00
|
|
|
|
|
|
|
limit: u32,
|
|
|
|
|
|
|
|
offset: u32,
|
|
|
|
|
|
|
|
// Query components for complex selects
|
|
|
|
query_map: Vec<QueryClause>,
|
|
|
|
|
|
|
|
// Query components for having clauses
|
|
|
|
having_map: Vec<QueryClause>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl QueryState {
|
|
|
|
pub fn new() -> QueryState {
|
|
|
|
QueryState::default()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-02 16:35:52 -04:00
|
|
|
/// The struct representing a query builder
|
2019-04-02 14:36:11 -04:00
|
|
|
#[derive(Default, Debug)]
|
|
|
|
pub struct QueryBuilder {
|
|
|
|
state: QueryState,
|
2019-04-02 16:35:52 -04:00
|
|
|
driver: Option<Box<dyn DatabaseDriver>>,
|
2019-04-02 14:36:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl QueryBuilder {
|
2019-04-02 16:35:52 -04:00
|
|
|
/// Creates a new QueryBuilder instance
|
2019-04-02 14:36:11 -04:00
|
|
|
pub fn new() -> QueryBuilder {
|
|
|
|
QueryBuilder {
|
|
|
|
state: QueryState::new(),
|
|
|
|
driver: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-03 13:29:08 -04:00
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// ! Select Queries
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
2019-04-02 17:23:52 -04:00
|
|
|
/// Set the fields to select from the database
|
|
|
|
pub fn select(mut self, fields: &str) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
2019-04-03 13:29:08 -04:00
|
|
|
// Adds the 'distinct' keyword to a query
|
|
|
|
pub fn distinct(mut self) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 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
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// ! 'Like' methods
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Creates a like clause in the sql statement
|
|
|
|
pub fn like(mut self, field: &str, value: Box<dyn Any>, position: LikeWildcard) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generates an OR Like clause
|
|
|
|
pub fn or_like(mut self, field: &str, value: Box<dyn Any>, position: LikeWildcard) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generates a NOI Like clause
|
|
|
|
pub fn not_like(mut self, field: &str, value: Box<dyn Any>, position: LikeWildcard) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generates an OR NOT Like clause
|
|
|
|
pub fn or_not_like(mut self, field: &str, value: Box<dyn Any>, position: LikeWildcard) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// ! Having methods
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
pub fn having(mut self, key:&str, value: Box<dyn Any>) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn or_having(mut self, key:&str, value: Box<dyn Any>) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// ! 'Where' methods
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/// Specify a condition for the where clause of the query
|
|
|
|
pub fn r#where(mut self, key: &str, value: Box<dyn Any>) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn or_where(mut self, key: &str, value: Box<dyn Any>) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn where_in(mut self, key: &str, value: Vec<Box<dyn Any>>) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn or_where_in(mut self, key: &str, value: Vec<Box<dyn Any>>) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn where_not_in(mut self, key: &str, value: Vec<Box<dyn Any>>) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn or_where_not_in(mut self, key: &str, value: Vec<Box<dyn Any>>) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// ! Other Query Modifier methods
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
2019-04-02 16:35:52 -04:00
|
|
|
/// Set a key and value for an insert or update query
|
2019-04-02 17:23:52 -04:00
|
|
|
pub fn set(mut self, key: &str, value: Box<dyn Any>) -> Self {
|
|
|
|
// @TODO figure a way to make this easier to use
|
|
|
|
self.state.set_array_keys.push(key.to_string());
|
2019-04-02 14:36:11 -04:00
|
|
|
self.state.values.push(value);
|
|
|
|
|
|
|
|
self
|
|
|
|
}
|
2019-04-02 17:23:52 -04:00
|
|
|
|
|
|
|
/// Set a map of data for an insert or update query
|
|
|
|
pub fn set_batch(mut self, data: HashMap<String, Box<dyn Any>>) -> Self {
|
|
|
|
for (key, value) in data {
|
|
|
|
self = self.set(&key, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2019-04-03 13:29:08 -04:00
|
|
|
// Add a table join to the query
|
|
|
|
pub fn join(mut self, table: &str, condition: &str, join_type: JoinType) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
2019-04-02 17:23:52 -04:00
|
|
|
|
2019-04-03 13:29:08 -04:00
|
|
|
pub fn group_by(mut self, field: &str) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn order_by(mut self, field: &str, direction: OrderDirection) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn limit(mut self, limit: u32, offset: u32) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// ! Query Grouping Methods
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
pub fn group_start(mut self) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn not_group_start(mut self) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn or_group_start(mut self) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn or_not_group_start(mut self) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn group_end(mut self) -> Self {
|
|
|
|
unimplemented!();
|
2019-04-02 17:23:52 -04:00
|
|
|
}
|
|
|
|
|
2019-04-03 13:29:08 -04:00
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// ! Query execution methods
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
2019-04-02 17:23:52 -04:00
|
|
|
/// Execute the built query
|
|
|
|
pub fn get(self) -> Box<dyn Any> {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
2019-04-03 13:29:08 -04:00
|
|
|
|
|
|
|
pub fn count_all(self, table: &str) -> u32 {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn insert(mut self, table: &str) {
|
|
|
|
// @TODO determine query result type
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn update(mut self, table: &str) {
|
|
|
|
// @TODO determine query result type
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn delete(mut self, table: &str, where_clause: &str) {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// ! SQL Returning Methods
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
pub fn get_compiled_select(self) -> String {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_compiled_insert(self) -> String {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_compiled_update(self) -> String {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_compiled_delete(self) -> String {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// ! Miscellaneous Methods
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
pub fn reset_query(mut self) -> Self {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
2019-04-02 14:36:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn set_key_value() {
|
2019-04-02 17:23:52 -04:00
|
|
|
let builder = QueryBuilder::new()
|
|
|
|
.set("foo", Box::new("bar"));
|
2019-04-02 14:36:11 -04:00
|
|
|
|
2019-04-02 17:23:52 -04:00
|
|
|
assert!(builder.state.values[0].is::<&str>());
|
2019-04-02 14:36:11 -04:00
|
|
|
}
|
2019-04-02 17:23:52 -04:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
// }
|
2019-04-02 14:36:11 -04:00
|
|
|
}
|