Put most of the features together for actually assembling the sql
This commit is contained in:
parent
35c0683891
commit
2e793284dd
61
src/enums.rs
Normal file
61
src/enums.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
//! Common enums
|
||||||
|
|
||||||
|
/// The position of the wildcard(s)
|
||||||
|
/// for a `like` clause
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum LikeWildcard {
|
||||||
|
/// Wildcard before search term
|
||||||
|
/// eg. `%foo`
|
||||||
|
Before,
|
||||||
|
|
||||||
|
/// Wildcard after the search term
|
||||||
|
/// eg. `foo%`
|
||||||
|
After,
|
||||||
|
|
||||||
|
/// Wildcards surrounding the search term
|
||||||
|
/// eg. `%foo%`
|
||||||
|
Both,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The type of SQL join
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum JoinType {
|
||||||
|
/// A `CROSS` join
|
||||||
|
Cross,
|
||||||
|
/// An `INNER` join
|
||||||
|
Inner,
|
||||||
|
/// An `OUTER` join
|
||||||
|
Outer,
|
||||||
|
/// A `LEFT (OUTER)` join
|
||||||
|
Left,
|
||||||
|
/// A `RIGHT (OUTER)` join
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The sort direction
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum OrderDirection {
|
||||||
|
/// Sort Ascending
|
||||||
|
Asc,
|
||||||
|
/// Sort Descending
|
||||||
|
Desc,
|
||||||
|
/// Random Sort (Not yet implemented!)
|
||||||
|
Rand,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The type of Query Clause
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum QueryClauseType {
|
||||||
|
/// Ending a parenthetical grouping
|
||||||
|
GroupEnd,
|
||||||
|
/// Starting a parenthetical grouping
|
||||||
|
GroupStart,
|
||||||
|
/// A join clause
|
||||||
|
Join,
|
||||||
|
/// A like clause
|
||||||
|
Like,
|
||||||
|
/// A where clause
|
||||||
|
Where,
|
||||||
|
/// A where in clause
|
||||||
|
WhereIn,
|
||||||
|
}
|
@ -8,6 +8,7 @@
|
|||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
|
|
||||||
pub mod drivers;
|
pub mod drivers;
|
||||||
|
pub mod enums;
|
||||||
pub mod query_builder;
|
pub mod query_builder;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
|
@ -1,64 +1,16 @@
|
|||||||
//! 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::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::drivers::{DatabaseDriver, DefaultDriver};
|
use crate::drivers::{DatabaseDriver, DefaultDriver};
|
||||||
|
use crate::enums::*;
|
||||||
use crate::split_map_join;
|
use crate::split_map_join;
|
||||||
use crate::types::Wild;
|
use crate::types::Wild;
|
||||||
|
|
||||||
/// The position of the wildcard(s)
|
use query_state::QueryState;
|
||||||
/// for a `like` clause
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum LikeWildcard {
|
|
||||||
/// Wildcard before search term
|
|
||||||
/// eg. `%foo`
|
|
||||||
Before,
|
|
||||||
|
|
||||||
/// Wildcard after the search term
|
|
||||||
/// eg. `foo%`
|
|
||||||
After,
|
|
||||||
|
|
||||||
/// Wildcards surrounding the search term
|
|
||||||
/// eg. `%foo%`
|
|
||||||
Both,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The type of SQL join
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum JoinType {
|
|
||||||
/// A `CROSS` join
|
|
||||||
Cross,
|
|
||||||
/// An `INNER` join
|
|
||||||
Inner,
|
|
||||||
/// An `OUTER` join
|
|
||||||
Outer,
|
|
||||||
/// A `LEFT (OUTER)` join
|
|
||||||
Left,
|
|
||||||
/// A `RIGHT (OUTER)` join
|
|
||||||
Right,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The sort direction
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum OrderDirection {
|
|
||||||
/// Sort Ascending
|
|
||||||
Asc,
|
|
||||||
/// Sort Descending
|
|
||||||
Desc,
|
|
||||||
/// Random Sort (Not yet implemented!)
|
|
||||||
Rand,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum QueryClauseType {
|
|
||||||
GroupEnd,
|
|
||||||
GroupStart,
|
|
||||||
Join,
|
|
||||||
Like,
|
|
||||||
Where,
|
|
||||||
WhereIn,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum QueryType {
|
enum QueryType {
|
||||||
@ -68,116 +20,6 @@ enum QueryType {
|
|||||||
Delete,
|
Delete,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(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<String>,
|
|
||||||
|
|
||||||
// Order by clause
|
|
||||||
order_array: HashMap<String, String>,
|
|
||||||
|
|
||||||
// Group by clause
|
|
||||||
group_array: Vec<String>,
|
|
||||||
|
|
||||||
// Values to apply to prepared statements
|
|
||||||
values: Vec<Wild>,
|
|
||||||
|
|
||||||
// Values to apply to where clauses in prepared statements
|
|
||||||
where_values: Vec<Wild>,
|
|
||||||
|
|
||||||
limit: Option<usize>,
|
|
||||||
|
|
||||||
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 {
|
|
||||||
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_array: 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 append_where_values(&mut self, val: Wild) -> &mut Self {
|
|
||||||
self.where_values.push(val);
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_query_map(
|
|
||||||
&mut self,
|
|
||||||
clause_type: QueryClauseType,
|
|
||||||
conj: &str,
|
|
||||||
s: &str,
|
|
||||||
) -> &mut Self {
|
|
||||||
self.query_map.push(QueryClause::new(clause_type, conj, s));
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_from_string(&mut self, s: &str) -> &mut Self {
|
|
||||||
self.from_string = s.to_owned();
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The struct representing a query builder
|
/// The struct representing a query builder
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct QueryBuilder {
|
pub struct QueryBuilder {
|
||||||
@ -232,20 +74,16 @@ impl QueryBuilder {
|
|||||||
|
|
||||||
/// Adds the `distinct` keyword to a query
|
/// Adds the `distinct` keyword to a query
|
||||||
pub fn distinct(&mut self) -> &mut Self {
|
pub fn distinct(&mut self) -> &mut Self {
|
||||||
self.state.select_string = String::from(" DISTINCT") + &self.state.select_string;
|
self.state.prepend_select_string(" DISTINCT");
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specify the database table to select from
|
/// Specify the database table to select from
|
||||||
pub fn from(&mut self, table_name: &str) -> &mut Self {
|
pub fn from(&mut self, table_name: &str) -> &mut Self {
|
||||||
let ident_vec = String::from(table_name)
|
let from_str = split_map_join(table_name, " ", |s| self.driver.quote_identifier(s));
|
||||||
.split(" ")
|
|
||||||
.into_iter()
|
|
||||||
.map(|s| self.driver.quote_identifier(s))
|
|
||||||
.collect::<Vec<String>>();
|
|
||||||
|
|
||||||
self.state.from_string = ident_vec.join(" ");
|
self.state.set_from_string(&from_str);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -295,9 +133,9 @@ impl QueryBuilder {
|
|||||||
/// Specify a condition for the `where` clause of the query
|
/// Specify a condition for the `where` clause of the query
|
||||||
pub fn r#where(&mut self, key: &str, op: &str, value: Wild) -> &mut Self {
|
pub fn r#where(&mut self, key: &str, op: &str, value: Wild) -> &mut Self {
|
||||||
// @TODO actually implement setting the keys for the where
|
// @TODO actually implement setting the keys for the where
|
||||||
self.state.where_values.push(value);
|
self.state.append_where_values(value);
|
||||||
|
|
||||||
self
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specify a condition for a `where` clause where a column has a value
|
/// Specify a condition for a `where` clause where a column has a value
|
||||||
@ -337,8 +175,7 @@ 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: Wild) -> &mut Self {
|
pub fn set(&mut self, key: &str, value: Wild) -> &mut Self {
|
||||||
// @TODO figure a way to make this easier to use
|
// @TODO figure a way to make this easier to use
|
||||||
self.state.set_array_keys.push(key.to_string());
|
self.state.append_set_array_keys(key).append_values(value);
|
||||||
self.state.values.push(value);
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -393,9 +230,11 @@ impl QueryBuilder {
|
|||||||
|
|
||||||
/// Add a group by clause to the query
|
/// Add a group by clause to the query
|
||||||
pub fn group_by(&mut self, field: &str) -> &mut Self {
|
pub fn group_by(&mut self, field: &str) -> &mut Self {
|
||||||
self.state.group_array.push(field.to_string());
|
self.state.append_group_array(field);
|
||||||
|
|
||||||
self.state.group_string = " GROUP BY ".to_string() + &self.state.group_array.join(",");
|
let group_string = String::from(" GROUP BY ") + &self.state.get_group_array().join(",");
|
||||||
|
|
||||||
|
self.state.set_group_string(&group_string);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -413,11 +252,11 @@ impl QueryBuilder {
|
|||||||
OrderDirection::Desc => String::from("DESC"),
|
OrderDirection::Desc => String::from("DESC"),
|
||||||
OrderDirection::Rand => String::from("RAND"),
|
OrderDirection::Rand => String::from("RAND"),
|
||||||
};
|
};
|
||||||
self.state.order_array.insert(field, dir);
|
self.state.append_order_map(&field, &dir);
|
||||||
|
|
||||||
let mut order_clauses: Vec<String> = vec![];
|
let mut order_clauses: Vec<String> = vec![];
|
||||||
|
|
||||||
for (f, dir) in &self.state.order_array {
|
for (f, dir) in self.state.get_order_map() {
|
||||||
let clause = String::clone(f) + " " + &dir;
|
let clause = String::clone(f) + " " + &dir;
|
||||||
&order_clauses.push(clause);
|
&order_clauses.push(clause);
|
||||||
}
|
}
|
||||||
@ -428,7 +267,7 @@ impl QueryBuilder {
|
|||||||
unimplemented!();
|
unimplemented!();
|
||||||
};
|
};
|
||||||
|
|
||||||
self.state.order_string = order_str;
|
self.state.set_order_string(&order_str);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -453,7 +292,7 @@ impl QueryBuilder {
|
|||||||
|
|
||||||
/// Start a logical grouping in the current query
|
/// Start a logical grouping in the current query
|
||||||
pub fn group_start(&mut self) -> &mut Self {
|
pub fn group_start(&mut self) -> &mut Self {
|
||||||
let conj = if self.state.query_map.len() == 0 {
|
let conj = if self.state.query_map_empty() {
|
||||||
" WHERE "
|
" WHERE "
|
||||||
} else {
|
} else {
|
||||||
" "
|
" "
|
||||||
@ -467,7 +306,7 @@ impl QueryBuilder {
|
|||||||
|
|
||||||
/// Start a logical grouping, prefixed with `not`
|
/// Start a logical grouping, prefixed with `not`
|
||||||
pub fn not_group_start(&mut self) -> &mut Self {
|
pub fn not_group_start(&mut self) -> &mut Self {
|
||||||
let conj = if self.state.query_map.len() == 0 {
|
let conj = if self.state.query_map_empty() {
|
||||||
" WHERE "
|
" WHERE "
|
||||||
} else {
|
} else {
|
||||||
" AND "
|
" AND "
|
||||||
@ -539,23 +378,29 @@ impl QueryBuilder {
|
|||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Get the generated SQL for a select query
|
/// Get the generated SQL for a select query
|
||||||
pub fn get_compiled_select(self) -> String {
|
pub fn get_compiled_select(&self) -> String {
|
||||||
unimplemented!();
|
// The table name should already be set from the `from` method
|
||||||
|
assert!(
|
||||||
|
self.state.get_from_string().len() > 0,
|
||||||
|
"You must use the `from` method to set the table name for a select query"
|
||||||
|
);
|
||||||
|
|
||||||
|
self.compile(QueryType::Select, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the generated SQL for an insert query
|
/// Get the generated SQL for an insert query
|
||||||
pub fn get_compiled_insert(self) -> String {
|
pub fn get_compiled_insert(&self, table: &str) -> String {
|
||||||
unimplemented!();
|
self.compile(QueryType::Insert, table)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the generated SQL for an update query
|
/// Get the generated SQL for an update query
|
||||||
pub fn get_compiled_update(self) -> String {
|
pub fn get_compiled_update(&self, table: &str) -> String {
|
||||||
unimplemented!();
|
self.compile(QueryType::Update, table)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the generated SQL for a delete query
|
/// Get the generated SQL for a delete query
|
||||||
pub fn get_compiled_delete(self) -> String {
|
pub fn get_compiled_delete(&self, table: &str) -> String {
|
||||||
unimplemented!();
|
self.compile(QueryType::Delete, table)
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@ -563,7 +408,7 @@ impl QueryBuilder {
|
|||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Get a new instance of the query builder
|
/// Get a new instance of the query builder
|
||||||
pub fn reset_query(mut self) -> Self {
|
pub fn reset(&mut self) -> &Self {
|
||||||
self.state = QueryState::new();
|
self.state = QueryState::new();
|
||||||
|
|
||||||
self
|
self
|
||||||
@ -594,7 +439,7 @@ impl QueryBuilder {
|
|||||||
LikeWildcard::Both => format!("%{}%", *string_val),
|
LikeWildcard::Both => format!("%{}%", *string_val),
|
||||||
};
|
};
|
||||||
|
|
||||||
let conj = if self.state.query_map.len() == 0 {
|
let conj = if self.state.query_map_empty() {
|
||||||
" WHERE "
|
" WHERE "
|
||||||
} else {
|
} else {
|
||||||
conj
|
conj
|
||||||
@ -624,11 +469,62 @@ impl QueryBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn compile(&self, query_type: QueryType, table: &str) -> String {
|
fn compile(&self, query_type: QueryType, table: &str) -> String {
|
||||||
unimplemented!();
|
// Get the base clause for the query
|
||||||
|
let base_sql = self.compile_type(query_type, &self.driver.quote_identifier(table));
|
||||||
|
|
||||||
|
let mut parts = vec![base_sql];
|
||||||
|
|
||||||
|
for clause in self.state.get_query_map() {
|
||||||
|
&parts.push(clause.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
&parts.push(self.state.get_group_string().to_string());
|
||||||
|
&parts.push(self.state.get_order_string().to_string());
|
||||||
|
|
||||||
|
for clause in self.state.get_having_map() {
|
||||||
|
&parts.push(clause.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let sql = parts.join("");
|
||||||
|
|
||||||
|
// @TODO handle limit / offset
|
||||||
|
|
||||||
|
sql
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_type(&self, query_type: QueryType, table: &str) -> String {
|
fn compile_type(&self, query_type: QueryType, table: &str) -> String {
|
||||||
unimplemented!();
|
match query_type {
|
||||||
|
QueryType::Select => {
|
||||||
|
let from = self.state.get_from_string();
|
||||||
|
let select = self.state.get_select_string();
|
||||||
|
|
||||||
|
let sql = format!("SELECT *\nFROM {}", from);
|
||||||
|
|
||||||
|
if select.len() > 0 {
|
||||||
|
sql.replace("*", select)
|
||||||
|
} else {
|
||||||
|
sql
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QueryType::Insert => {
|
||||||
|
let set_array_keys = self.state.get_set_array_keys();
|
||||||
|
let param_count = set_array_keys.len();
|
||||||
|
let params = vec!["?"; param_count];
|
||||||
|
|
||||||
|
format!(
|
||||||
|
"INSERT INTO {} ({})\nVALUES({})",
|
||||||
|
table,
|
||||||
|
set_array_keys.join(","),
|
||||||
|
params.join(",")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
QueryType::Update => {
|
||||||
|
let set_string = self.state.get_set_string();
|
||||||
|
|
||||||
|
format!("UPDATE {}\nSET {}", table, set_string)
|
||||||
|
}
|
||||||
|
QueryType::Delete => format!("DELETE FROM {}", table),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -642,11 +538,14 @@ mod tests {
|
|||||||
|
|
||||||
qb.set("foo", Box::new("bar"));
|
qb.set("foo", Box::new("bar"));
|
||||||
|
|
||||||
assert_eq!(qb.state.set_array_keys[0], "foo");
|
assert_eq!(qb.state.get_set_array_keys()[0], "foo");
|
||||||
assert!(qb.state.values[0].is::<&str>());
|
assert!(qb.state.get_values()[0].is::<&str>());
|
||||||
|
|
||||||
// @TODO find a way to make this kind of operation much more ergonomic
|
// @TODO find a way to make this kind of operation much more ergonomic
|
||||||
assert_eq!(*qb.state.values[0].downcast_ref::<&str>().unwrap(), "bar");
|
assert_eq!(
|
||||||
|
*qb.state.get_values()[0].downcast_ref::<&str>().unwrap(),
|
||||||
|
"bar"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -667,7 +566,7 @@ mod tests {
|
|||||||
qb.set_map(authors);
|
qb.set_map(authors);
|
||||||
|
|
||||||
// assert_eq!(qb.state.set_array_keys[0], "Chinua Achebe");
|
// assert_eq!(qb.state.set_array_keys[0], "Chinua Achebe");
|
||||||
assert_eq!(qb.state.set_array_keys.len(), 3);
|
assert_eq!(qb.state.get_set_array_keys().len(), 3);
|
||||||
assert_eq!(qb.state.values.len(), 3);
|
assert_eq!(qb.state.get_values().len(), 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
224
src/query_builder/query_state.rs
Normal file
224
src/query_builder/query_state.rs
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub 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)]
|
||||||
|
pub 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<String>,
|
||||||
|
|
||||||
|
// Order by clause
|
||||||
|
order_map: HashMap<String, String>,
|
||||||
|
|
||||||
|
// Group by clause
|
||||||
|
group_array: Vec<String>,
|
||||||
|
|
||||||
|
// Values to apply to prepared statements
|
||||||
|
values: Vec<Wild>,
|
||||||
|
|
||||||
|
// Values to apply to where clauses in prepared statements
|
||||||
|
where_values: Vec<Wild>,
|
||||||
|
|
||||||
|
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 {
|
||||||
|
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,
|
||||||
|
clause_type: QueryClauseType,
|
||||||
|
conj: &str,
|
||||||
|
s: &str,
|
||||||
|
) -> &mut Self {
|
||||||
|
self.having_map.push(QueryClause::new(clause_type, 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: Wild) -> &mut Self {
|
||||||
|
self.values.push(val);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_where_values(&mut self, val: Wild) -> &mut Self {
|
||||||
|
self.where_values.push(val);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_query_map(
|
||||||
|
&mut self,
|
||||||
|
clause_type: QueryClauseType,
|
||||||
|
conj: &str,
|
||||||
|
s: &str,
|
||||||
|
) -> &mut Self {
|
||||||
|
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<Wild> {
|
||||||
|
&self.values
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_where_values(&self) -> &Vec<Wild> {
|
||||||
|
&self.where_values
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn having_map_empty(&self) -> bool {
|
||||||
|
self.having_map.len() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn query_map_empty(&self) -> bool {
|
||||||
|
self.query_map.len() == 0
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user