Fewer boxes!
This commit is contained in:
parent
f34a403584
commit
2aa7efa670
@ -1,6 +1,12 @@
|
|||||||
//! # StringQB
|
//! # StringQB
|
||||||
//!
|
//!
|
||||||
//! A query builder using mostly strings, with methods following common SQL syntax
|
//! A query builder using mostly strings, with methods following common SQL syntax
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! use stringqb::prelude::*;
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
// Temporarily silence unused variables and uncalled code warnings
|
// Temporarily silence unused variables and uncalled code warnings
|
||||||
// @TODO remove when most of the code is implemented
|
// @TODO remove when most of the code is implemented
|
||||||
@ -25,12 +31,15 @@ pub mod prelude {
|
|||||||
pub use crate::query_builder::QueryBuilder;
|
pub use crate::query_builder::QueryBuilder;
|
||||||
|
|
||||||
#[cfg(feature = "postgres")]
|
#[cfg(feature = "postgres")]
|
||||||
|
/// Postgres Driver
|
||||||
pub use crate::drivers::postgres::PostgresDriver;
|
pub use crate::drivers::postgres::PostgresDriver;
|
||||||
|
|
||||||
#[cfg(feature = "sqlite")]
|
#[cfg(feature = "sqlite")]
|
||||||
|
/// SQLite Driver
|
||||||
pub use crate::drivers::sqlite::SQLiteDriver;
|
pub use crate::drivers::sqlite::SQLiteDriver;
|
||||||
|
|
||||||
#[cfg(feature = "mysql")]
|
#[cfg(feature = "mysql")]
|
||||||
|
/// MySQL Driver
|
||||||
pub use crate::drivers::mysql::MySQLDriver;
|
pub use crate::drivers::mysql::MySQLDriver;
|
||||||
|
|
||||||
// MSSQL is missing on purpose, as it is not a real priority to actually implement
|
// MSSQL is missing on purpose, as it is not a real priority to actually implement
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
//! Query Builder
|
//! Query Builder
|
||||||
//!
|
//!
|
||||||
//! The QueryBuilder creates sql queries from chained methods
|
//! The QueryBuilder creates sql queries from chained methods
|
||||||
mod query_state;
|
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
@ -10,7 +8,6 @@ use crate::drivers::{DatabaseDriver, DefaultDriver};
|
|||||||
use crate::enums::*;
|
use crate::enums::*;
|
||||||
use crate::fns::split_map_join;
|
use crate::fns::split_map_join;
|
||||||
|
|
||||||
use query_state::QueryState;
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -25,7 +22,7 @@ enum QueryType {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct QueryBuilder {
|
pub struct QueryBuilder {
|
||||||
/// The struct to store the query builder info
|
/// The struct to store the query builder info
|
||||||
pub state: QueryState,
|
state: QueryState,
|
||||||
driver: Box<dyn DatabaseDriver>,
|
driver: Box<dyn DatabaseDriver>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,15 +155,15 @@ impl QueryBuilder {
|
|||||||
/// # use stringqb::prelude::*;
|
/// # use stringqb::prelude::*;
|
||||||
/// # let mut qb = stringqb::query_builder::QueryBuilder::default();
|
/// # let mut qb = stringqb::query_builder::QueryBuilder::default();
|
||||||
/// // Search for a value that ends with "foo"
|
/// // Search for a value that ends with "foo"
|
||||||
/// qb.like("field", Box::new("foo"), LikeWildcard::Before);
|
/// qb.like("field", String::from("foo"), LikeWildcard::Before);
|
||||||
///
|
///
|
||||||
/// // Search for a value that starts with "foo"
|
/// // Search for a value that starts with "foo"
|
||||||
/// qb.like("field", Box::new("foo"), LikeWildcard::After);
|
/// qb.like("field", String::from("foo"), LikeWildcard::After);
|
||||||
///
|
///
|
||||||
/// // Search for a value that has "foo" in it
|
/// // Search for a value that has "foo" in it
|
||||||
/// qb.like("field", Box::new("foo"), LikeWildcard::Both);
|
/// qb.like("field", String::from("foo"), LikeWildcard::Both);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn like(&mut self, field: &str, value: Box<dyn Any>, position: LikeWildcard) -> &mut Self {
|
pub fn like(&mut self, field: &str, value: (impl Any), position: LikeWildcard) -> &mut Self {
|
||||||
self._like(field, value, position, "LIKE", "AND")
|
self._like(field, value, position, "LIKE", "AND")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +171,7 @@ impl QueryBuilder {
|
|||||||
pub fn or_like(
|
pub fn or_like(
|
||||||
&mut self,
|
&mut self,
|
||||||
field: &str,
|
field: &str,
|
||||||
value: Box<dyn Any>,
|
value: (impl Any),
|
||||||
position: LikeWildcard,
|
position: LikeWildcard,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self._like(field, value, position, "LIKE", "OR")
|
self._like(field, value, position, "LIKE", "OR")
|
||||||
@ -184,7 +181,7 @@ impl QueryBuilder {
|
|||||||
pub fn not_like(
|
pub fn not_like(
|
||||||
&mut self,
|
&mut self,
|
||||||
field: &str,
|
field: &str,
|
||||||
value: Box<dyn Any>,
|
value: (impl Any),
|
||||||
position: LikeWildcard,
|
position: LikeWildcard,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self._like(field, value, position, "NOT LIKE", "AND")
|
self._like(field, value, position, "NOT LIKE", "AND")
|
||||||
@ -194,7 +191,7 @@ impl QueryBuilder {
|
|||||||
pub fn or_not_like(
|
pub fn or_not_like(
|
||||||
&mut self,
|
&mut self,
|
||||||
field: &str,
|
field: &str,
|
||||||
value: Box<dyn Any>,
|
value: (impl Any),
|
||||||
position: LikeWildcard,
|
position: LikeWildcard,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self._like(field, value, position, "NOT LIKE", "OR")
|
self._like(field, value, position, "NOT LIKE", "OR")
|
||||||
@ -215,12 +212,12 @@ impl QueryBuilder {
|
|||||||
/// // Other operators can be used with a separating space
|
/// // Other operators can be used with a separating space
|
||||||
/// qb.having("clues >=", vec![Box::new(4)]);
|
/// qb.having("clues >=", vec![Box::new(4)]);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn having(&mut self, key: &str, value: Vec<Box<dyn Any>>) -> &mut Self {
|
pub fn having(&mut self, key: &str, value: Vec<(impl Any)>) -> &mut Self {
|
||||||
self._having(key, value, "AND")
|
self._having(key, value, "AND")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a `having` clause to the query, prefixed with an `or`
|
/// Add a `having` clause to the query, prefixed with an `or`
|
||||||
pub fn or_having(&mut self, key: &str, value: Vec<Box<dyn Any>>) -> &mut Self {
|
pub fn or_having(&mut self, key: &str, value: Vec<(impl Any)>) -> &mut Self {
|
||||||
self._having(key, value, "OR")
|
self._having(key, value, "OR")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +226,7 @@ impl QueryBuilder {
|
|||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Alias method for `r#where`.
|
/// Alias method for `r#where`.
|
||||||
pub fn filter(&mut self, key: &str, value: Box<dyn Any>) -> &mut Self {
|
pub fn filter(&mut self, key: &str, value: (impl Any)) -> &mut Self {
|
||||||
self.r#where(key, value)
|
self.r#where(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,32 +243,32 @@ impl QueryBuilder {
|
|||||||
/// // Other operators can be used with a separating space
|
/// // Other operators can be used with a separating space
|
||||||
/// qb.r#where("key >", Box::new(4));
|
/// qb.r#where("key >", Box::new(4));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn r#where(&mut self, key: &str, value: Box<dyn Any>) -> &mut Self {
|
pub fn r#where(&mut self, key: &str, value: (impl Any)) -> &mut Self {
|
||||||
self._where_string(key, value, "AND")
|
self._where_string(key, value, "AND")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specify a condition for the `where` clause of the query, prefixed with `or`
|
/// Specify a condition for the `where` clause of the query, prefixed with `or`
|
||||||
pub fn or_where(&mut self, key: &str, value: Box<dyn Any>) -> &mut Self {
|
pub fn or_where(&mut self, key: &str, value: (impl Any)) -> &mut Self {
|
||||||
self._where_string(key, value, "OR")
|
self._where_string(key, value, "OR")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specify a `where in` clause for the query
|
/// Specify a `where in` clause for the query
|
||||||
pub fn where_in(&mut self, key: &str, values: Vec<Box<dyn Any>>) -> &mut Self {
|
pub fn where_in(&mut self, key: &str, values: Vec<(impl Any)>) -> &mut Self {
|
||||||
self._where_in(key, values, "IN", "AND")
|
self._where_in(key, values, "IN", "AND")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specify a `where in` clause for the query, prefixed with `or`
|
/// Specify a `where in` clause for the query, prefixed with `or`
|
||||||
pub fn or_where_in(&mut self, key: &str, values: Vec<Box<dyn Any>>) -> &mut Self {
|
pub fn or_where_in(&mut self, key: &str, values: Vec<(impl Any)>) -> &mut Self {
|
||||||
self._where_in(key, values, "IN", "OR")
|
self._where_in(key, values, "IN", "OR")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specify a `where not in` clause for the query
|
/// Specify a `where not in` clause for the query
|
||||||
pub fn where_not_in(&mut self, key: &str, values: Vec<Box<dyn Any>>) -> &mut Self {
|
pub fn where_not_in(&mut self, key: &str, values: Vec<(impl Any)>) -> &mut Self {
|
||||||
self._where_in(key, values, "NOT IN", "AND")
|
self._where_in(key, values, "NOT IN", "AND")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specify a `where not in` clause for the query, prefixed with `or`
|
/// Specify a `where not in` clause for the query, prefixed with `or`
|
||||||
pub fn or_where_not_in(&mut self, key: &str, values: Vec<Box<dyn Any>>) -> &mut Self {
|
pub fn or_where_not_in(&mut self, key: &str, values: Vec<(impl Any)>) -> &mut Self {
|
||||||
self._where_in(key, values, "NOT IN", "OR")
|
self._where_in(key, values, "NOT IN", "OR")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,16 +277,16 @@ impl QueryBuilder {
|
|||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Set a key and value for an insert or update query
|
/// Set a key and value for an insert or update query
|
||||||
pub fn set(&mut self, key: &str, value: Box<dyn Any>) -> &mut Self {
|
pub fn set(&mut self, key: &str, value: (impl Any)) -> &mut Self {
|
||||||
// @TODO figure a way to make this easier to use
|
// @TODO figure a way to make this easier to use
|
||||||
let key = self.driver.quote_identifier(key);
|
let key = self.driver.quote_identifier(key);
|
||||||
self.state.append_set_array_keys(&key).append_values(value);
|
self.state.append_set_array_keys(&key).append_values(Box::new(value));
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a map of data for an insert or update query
|
/// Set a map of data for an insert or update query
|
||||||
pub fn set_map(&mut self, data: HashMap<String, Box<dyn Any>>) -> &mut Self {
|
pub fn set_map(&mut self, data: HashMap<String, (impl Any)>) -> &mut Self {
|
||||||
for (key, value) in data {
|
for (key, value) in data {
|
||||||
self.set(&key, value);
|
self.set(&key, value);
|
||||||
}
|
}
|
||||||
@ -520,7 +517,7 @@ impl QueryBuilder {
|
|||||||
fn _like(
|
fn _like(
|
||||||
&mut self,
|
&mut self,
|
||||||
field: &str,
|
field: &str,
|
||||||
value: Box<dyn Any>,
|
value: (impl Any),
|
||||||
position: LikeWildcard,
|
position: LikeWildcard,
|
||||||
like: &str,
|
like: &str,
|
||||||
conj: &str,
|
conj: &str,
|
||||||
@ -529,13 +526,14 @@ impl QueryBuilder {
|
|||||||
|
|
||||||
let like = format!("{} {} ?", field, like);
|
let like = format!("{} {} ?", field, like);
|
||||||
|
|
||||||
let string_val = value.downcast::<String>().unwrap();
|
let value: Box<dyn Any + 'static> = Box::new(value);
|
||||||
|
let string_val = value.downcast_ref::<String>().unwrap();
|
||||||
|
|
||||||
// @TODO Properly parse types of `value` for string formatting
|
// @TODO Properly parse types of `value` for string formatting
|
||||||
let value = match position {
|
let value = match position {
|
||||||
LikeWildcard::Before => format!("%{}", *string_val),
|
LikeWildcard::Before => format!("%{}", string_val),
|
||||||
LikeWildcard::After => format!("{}%s", *string_val),
|
LikeWildcard::After => format!("{}%s", string_val),
|
||||||
LikeWildcard::Both => format!("%{}%", *string_val),
|
LikeWildcard::Both => format!("%{}%", string_val),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.state
|
self.state
|
||||||
@ -545,7 +543,7 @@ impl QueryBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _having(&mut self, key: &str, values: Vec<Box<dyn Any>>, conj: &str) -> &mut Self {
|
fn _having(&mut self, key: &str, values: Vec<(impl Any)>, conj: &str) -> &mut Self {
|
||||||
let keys = self._where(key, values);
|
let keys = self._where(key, values);
|
||||||
|
|
||||||
for k in keys {
|
for k in keys {
|
||||||
@ -573,9 +571,9 @@ impl QueryBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _where(&mut self, key: &str, values: Vec<Box<dyn Any>>) -> Vec<String> {
|
fn _where(&mut self, key: &str, values: Vec<(impl Any)>) -> Vec<String> {
|
||||||
for x in values {
|
for x in values {
|
||||||
self.state.append_where_values(x);
|
self.state.append_where_values(Box::new(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
vec![String::from(key)]
|
vec![String::from(key)]
|
||||||
@ -584,7 +582,7 @@ impl QueryBuilder {
|
|||||||
fn _where_in(
|
fn _where_in(
|
||||||
&mut self,
|
&mut self,
|
||||||
key: &str,
|
key: &str,
|
||||||
values: Vec<Box<dyn Any>>,
|
values: Vec<(impl Any)>,
|
||||||
in_str: &str,
|
in_str: &str,
|
||||||
conj: &str,
|
conj: &str,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
@ -592,7 +590,7 @@ impl QueryBuilder {
|
|||||||
let placeholders = vec!["?"; values.len()];
|
let placeholders = vec!["?"; values.len()];
|
||||||
|
|
||||||
for value in values {
|
for value in values {
|
||||||
self.state.append_where_values(value);
|
self.state.append_where_values(Box::new(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
let str = format!("{} {} ({}) ", key, in_str, placeholders.join(","));
|
let str = format!("{} {} ({}) ", key, in_str, placeholders.join(","));
|
||||||
@ -603,7 +601,7 @@ impl QueryBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _where_string(&mut self, key: &str, value: Box<dyn Any>, conj: &str) -> &mut Self {
|
fn _where_string(&mut self, key: &str, value: impl Any, conj: &str) -> &mut Self {
|
||||||
let keys = self._where(key, vec![value]);
|
let keys = self._where(key, vec![value]);
|
||||||
|
|
||||||
for k in keys {
|
for k in keys {
|
||||||
@ -704,6 +702,233 @@ impl QueryBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct QueryClause {
|
||||||
|
clause_type: QueryClauseType,
|
||||||
|
conjunction: String,
|
||||||
|
string: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QueryClause {
|
||||||
|
pub fn new(clause_type: QueryClauseType, conjunction: &str, string: &str) -> Self {
|
||||||
|
QueryClause {
|
||||||
|
clause_type,
|
||||||
|
conjunction: conjunction.to_string(),
|
||||||
|
string: string.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_string(&self) -> String {
|
||||||
|
format!("{}{}", self.conjunction, self.string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct QueryState {
|
||||||
|
pub explain: bool,
|
||||||
|
|
||||||
|
select_string: String,
|
||||||
|
from_string: String,
|
||||||
|
set_string: String,
|
||||||
|
order_string: String,
|
||||||
|
group_string: String,
|
||||||
|
|
||||||
|
// Keys for insert/update statement
|
||||||
|
set_array_keys: Vec<String>,
|
||||||
|
|
||||||
|
// Order by clause
|
||||||
|
order_map: HashMap<String, String>,
|
||||||
|
|
||||||
|
// Group by clause
|
||||||
|
group_array: Vec<String>,
|
||||||
|
|
||||||
|
// Values to apply to prepared statements
|
||||||
|
values: Vec<Box<Any>>,
|
||||||
|
|
||||||
|
// Values to apply to where clauses in prepared statements
|
||||||
|
where_values: Vec<Box<Any>>,
|
||||||
|
|
||||||
|
pub limit: Option<usize>,
|
||||||
|
|
||||||
|
pub offset: Option<usize>,
|
||||||
|
|
||||||
|
// Query components for complex selects
|
||||||
|
query_map: Vec<QueryClause>,
|
||||||
|
|
||||||
|
// Query components for having clauses
|
||||||
|
having_map: Vec<QueryClause>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for QueryState {
|
||||||
|
fn default() -> Self {
|
||||||
|
QueryState {
|
||||||
|
explain: false,
|
||||||
|
|
||||||
|
select_string: String::from(""),
|
||||||
|
from_string: String::from(""),
|
||||||
|
set_string: String::from(""),
|
||||||
|
order_string: String::from(""),
|
||||||
|
group_string: String::from(""),
|
||||||
|
|
||||||
|
set_array_keys: vec![],
|
||||||
|
order_map: HashMap::new(),
|
||||||
|
group_array: vec![],
|
||||||
|
values: vec![],
|
||||||
|
where_values: vec![],
|
||||||
|
|
||||||
|
limit: None,
|
||||||
|
offset: None,
|
||||||
|
|
||||||
|
query_map: vec![],
|
||||||
|
having_map: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QueryState {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
QueryState::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_select_string(&mut self, s: &str) -> &mut Self {
|
||||||
|
self.select_string += s;
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prepend_select_string(&mut self, s: &str) -> &mut Self {
|
||||||
|
self.select_string = String::from(s) + &self.select_string;
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_group_array(&mut self, field: &str) -> &mut Self {
|
||||||
|
self.group_array.push(String::from(field));
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_having_map(&mut self, conj: &str, s: &str) -> &mut Self {
|
||||||
|
let conj = if self.having_map.len() == 0 {
|
||||||
|
String::from(" HAVING ")
|
||||||
|
} else {
|
||||||
|
format!(" {} ", conj)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.having_map
|
||||||
|
.push(QueryClause::new(QueryClauseType::Having, &conj, s));
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_order_map(&mut self, key: &str, dir: &str) -> &mut Self {
|
||||||
|
self.order_map.insert(String::from(key), String::from(dir));
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_set_array_keys(&mut self, key: &str) -> &mut Self {
|
||||||
|
self.set_array_keys.push(key.to_string());
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_values(&mut self, val: Box<Any>) -> &mut Self {
|
||||||
|
self.values.push(val);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_where_values(&mut self, val: Box<Any>) -> &mut Self {
|
||||||
|
self.where_values.push(val);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_query_map(
|
||||||
|
&mut self,
|
||||||
|
clause_type: QueryClauseType,
|
||||||
|
conj: &str,
|
||||||
|
s: &str,
|
||||||
|
) -> &mut Self {
|
||||||
|
let conj = if self.query_map.len() == 0 {
|
||||||
|
" WHERE "
|
||||||
|
} else {
|
||||||
|
conj
|
||||||
|
};
|
||||||
|
|
||||||
|
self.query_map.push(QueryClause::new(clause_type, conj, s));
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_from_string(&self) -> &str {
|
||||||
|
&self.from_string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_group_array(&self) -> &Vec<String> {
|
||||||
|
&self.group_array
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_group_string(&self) -> &str {
|
||||||
|
&self.group_string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_having_map(&self) -> &Vec<QueryClause> {
|
||||||
|
&self.having_map
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_query_map(&self) -> &Vec<QueryClause> {
|
||||||
|
&self.query_map
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_select_string(&self) -> &str {
|
||||||
|
&self.select_string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_set_array_keys(&self) -> &Vec<String> {
|
||||||
|
&self.set_array_keys
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_set_string(&self) -> &str {
|
||||||
|
&self.set_string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_order_map(&self) -> &HashMap<String, String> {
|
||||||
|
&self.order_map
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_order_string(&self) -> &str {
|
||||||
|
&self.order_string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_values(&self) -> &Vec<Box<Any>> {
|
||||||
|
&self.values
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_where_values(&self) -> &Vec<Box<Any>> {
|
||||||
|
&self.where_values
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_from_string(&mut self, s: &str) -> &mut Self {
|
||||||
|
self.from_string = String::from(s);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_group_string(&mut self, s: &str) -> &mut Self {
|
||||||
|
self.group_string = String::from(s);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_order_string(&mut self, order_string: &str) -> &mut Self {
|
||||||
|
self.order_string = String::from(order_string);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -712,7 +937,7 @@ mod tests {
|
|||||||
fn set_key_value() {
|
fn set_key_value() {
|
||||||
let mut qb = QueryBuilder::default();
|
let mut qb = QueryBuilder::default();
|
||||||
|
|
||||||
qb.set("foo", Box::new("bar"));
|
qb.set("foo", "bar");
|
||||||
|
|
||||||
assert_eq!(qb.state.get_set_array_keys()[0], "\"foo\"");
|
assert_eq!(qb.state.get_set_array_keys()[0], "\"foo\"");
|
||||||
assert!(qb.state.get_values()[0].is::<&str>());
|
assert!(qb.state.get_values()[0].is::<&str>());
|
||||||
@ -728,16 +953,16 @@ mod tests {
|
|||||||
fn set_hashmap() {
|
fn set_hashmap() {
|
||||||
let mut qb = QueryBuilder::default();
|
let mut qb = QueryBuilder::default();
|
||||||
|
|
||||||
let mut authors: HashMap<String, Box<dyn Any>> = HashMap::new();
|
let mut authors = HashMap::new();
|
||||||
authors.insert(
|
authors.insert(
|
||||||
String::from("Chinua Achebe"),
|
String::from("Chinua Achebe"),
|
||||||
Box::new(String::from("Nigeria")),
|
String::from("Nigeria"),
|
||||||
);
|
);
|
||||||
authors.insert(
|
authors.insert(
|
||||||
String::from("Rabindranath Tagore"),
|
String::from("Rabindranath Tagore"),
|
||||||
Box::new(String::from("India")),
|
String::from("India"),
|
||||||
);
|
);
|
||||||
authors.insert(String::from("Anita Nair"), Box::new(String::from("India")));
|
authors.insert(String::from("Anita Nair"), String::from("India"));
|
||||||
|
|
||||||
qb.set_map(authors);
|
qb.set_map(authors);
|
||||||
|
|
||||||
@ -753,12 +978,12 @@ mod tests {
|
|||||||
qb.from("test").where_in(
|
qb.from("test").where_in(
|
||||||
"foo",
|
"foo",
|
||||||
vec![
|
vec![
|
||||||
Box::new(0),
|
0,
|
||||||
Box::new(1),
|
1,
|
||||||
Box::new(2),
|
2,
|
||||||
Box::new(3),
|
3,
|
||||||
Box::new(4),
|
4,
|
||||||
Box::new(5),
|
5,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,228 +0,0 @@
|
|||||||
use super::*;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct QueryClause {
|
|
||||||
pub clause_type: QueryClauseType,
|
|
||||||
conjunction: String,
|
|
||||||
string: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl QueryClause {
|
|
||||||
pub fn new(clause_type: QueryClauseType, conjunction: &str, string: &str) -> Self {
|
|
||||||
QueryClause {
|
|
||||||
clause_type,
|
|
||||||
conjunction: conjunction.to_string(),
|
|
||||||
string: string.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_string(&self) -> String {
|
|
||||||
format!("{}{}", self.conjunction, self.string)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct QueryState {
|
|
||||||
pub explain: bool,
|
|
||||||
|
|
||||||
select_string: String,
|
|
||||||
from_string: String,
|
|
||||||
set_string: String,
|
|
||||||
order_string: String,
|
|
||||||
group_string: String,
|
|
||||||
|
|
||||||
// Keys for insert/update statement
|
|
||||||
set_array_keys: Vec<String>,
|
|
||||||
|
|
||||||
// Order by clause
|
|
||||||
order_map: HashMap<String, String>,
|
|
||||||
|
|
||||||
// Group by clause
|
|
||||||
group_array: Vec<String>,
|
|
||||||
|
|
||||||
// Values to apply to prepared statements
|
|
||||||
values: Vec<Box<Any>>,
|
|
||||||
|
|
||||||
// Values to apply to where clauses in prepared statements
|
|
||||||
where_values: Vec<Box<Any>>,
|
|
||||||
|
|
||||||
pub limit: Option<usize>,
|
|
||||||
|
|
||||||
pub offset: Option<usize>,
|
|
||||||
|
|
||||||
// Query components for complex selects
|
|
||||||
query_map: Vec<QueryClause>,
|
|
||||||
|
|
||||||
// Query components for having clauses
|
|
||||||
having_map: Vec<QueryClause>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for QueryState {
|
|
||||||
fn default() -> Self {
|
|
||||||
QueryState {
|
|
||||||
explain: false,
|
|
||||||
|
|
||||||
select_string: String::from(""),
|
|
||||||
from_string: String::from(""),
|
|
||||||
set_string: String::from(""),
|
|
||||||
order_string: String::from(""),
|
|
||||||
group_string: String::from(""),
|
|
||||||
|
|
||||||
set_array_keys: vec![],
|
|
||||||
order_map: HashMap::new(),
|
|
||||||
group_array: vec![],
|
|
||||||
values: vec![],
|
|
||||||
where_values: vec![],
|
|
||||||
|
|
||||||
limit: None,
|
|
||||||
offset: None,
|
|
||||||
|
|
||||||
query_map: vec![],
|
|
||||||
having_map: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl QueryState {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
QueryState::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_select_string(&mut self, s: &str) -> &mut Self {
|
|
||||||
self.select_string += s;
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn prepend_select_string(&mut self, s: &str) -> &mut Self {
|
|
||||||
self.select_string = String::from(s) + &self.select_string;
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_group_array(&mut self, field: &str) -> &mut Self {
|
|
||||||
self.group_array.push(String::from(field));
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_having_map(&mut self, conj: &str, s: &str) -> &mut Self {
|
|
||||||
let conj = if self.having_map.len() == 0 {
|
|
||||||
String::from(" HAVING ")
|
|
||||||
} else {
|
|
||||||
format!(" {} ", conj)
|
|
||||||
};
|
|
||||||
|
|
||||||
self.having_map
|
|
||||||
.push(QueryClause::new(QueryClauseType::Having, &conj, s));
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_order_map(&mut self, key: &str, dir: &str) -> &mut Self {
|
|
||||||
self.order_map.insert(String::from(key), String::from(dir));
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_set_array_keys(&mut self, key: &str) -> &mut Self {
|
|
||||||
self.set_array_keys.push(key.to_string());
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_values(&mut self, val: Box<Any>) -> &mut Self {
|
|
||||||
self.values.push(val);
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_where_values(&mut self, val: Box<Any>) -> &mut Self {
|
|
||||||
self.where_values.push(val);
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_query_map(
|
|
||||||
&mut self,
|
|
||||||
clause_type: QueryClauseType,
|
|
||||||
conj: &str,
|
|
||||||
s: &str,
|
|
||||||
) -> &mut Self {
|
|
||||||
let conj = if self.query_map.len() == 0 {
|
|
||||||
" WHERE "
|
|
||||||
} else {
|
|
||||||
conj
|
|
||||||
};
|
|
||||||
|
|
||||||
self.query_map.push(QueryClause::new(clause_type, conj, s));
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_from_string(&self) -> &str {
|
|
||||||
&self.from_string
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_group_array(&self) -> &Vec<String> {
|
|
||||||
&self.group_array
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_group_string(&self) -> &str {
|
|
||||||
&self.group_string
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_having_map(&self) -> &Vec<QueryClause> {
|
|
||||||
&self.having_map
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_query_map(&self) -> &Vec<QueryClause> {
|
|
||||||
&self.query_map
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_select_string(&self) -> &str {
|
|
||||||
&self.select_string
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_set_array_keys(&self) -> &Vec<String> {
|
|
||||||
&self.set_array_keys
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_set_string(&self) -> &str {
|
|
||||||
&self.set_string
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_order_map(&self) -> &HashMap<String, String> {
|
|
||||||
&self.order_map
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_order_string(&self) -> &str {
|
|
||||||
&self.order_string
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_values(&self) -> &Vec<Box<Any>> {
|
|
||||||
&self.values
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_where_values(&self) -> &Vec<Box<Any>> {
|
|
||||||
&self.where_values
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_from_string(&mut self, s: &str) -> &mut Self {
|
|
||||||
self.from_string = String::from(s);
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_group_string(&mut self, s: &str) -> &mut Self {
|
|
||||||
self.group_string = String::from(s);
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_order_string(&mut self, order_string: &str) -> &mut Self {
|
|
||||||
self.order_string = String::from(order_string);
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user