stringqb/src/query_builder.rs

103 lines
2.1 KiB
Rust
Raw Normal View History

2019-04-02 16:35:52 -04:00
//! QueryBuilder
//!
//! The QueryBuilder creates sql queries from chained methods
use std::any::{Any, TypeId};
2019-04-02 14:36:11 -04:00
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
pub set_array_keys: Vec<String>,
// 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 16:35:52 -04:00
pub 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 16:35:52 -04:00
pub 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-02 16:35:52 -04:00
/// Set a key and value for an insert or update query
pub fn set(mut self, key: String, value: Box<dyn Any>) -> Self {
2019-04-02 14:36:11 -04:00
self.state.set_array_keys.push(key);
self.state.values.push(value);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn set_key_value() {
let builder = QueryBuilder::new();
2019-04-02 16:35:52 -04:00
let builder = builder.set("foo".to_string(), Box::new("bar".to_string()));
2019-04-02 14:36:11 -04:00
2019-04-02 16:35:52 -04:00
assert!(builder.state.values[0].is::<String>());
2019-04-02 14:36:11 -04:00
}
}