Implement the remaining query builder methods, except those that call the database

This commit is contained in:
Timothy Warren 2019-04-16 15:51:27 -04:00
parent 9183e2f475
commit 296e87e3e9
4 changed files with 75 additions and 18 deletions

View File

@ -44,7 +44,7 @@ pub enum OrderDirection {
} }
/// The type of Query Clause /// The type of Query Clause
#[derive(Debug)] #[derive(Debug, PartialEq)]
pub enum QueryClauseType { pub enum QueryClauseType {
/// Ending a parenthetical grouping /// Ending a parenthetical grouping
GroupEnd, GroupEnd,

View File

@ -11,7 +11,7 @@ fn main() {
.set("buzz", Box::new((1, 2.0, true, 'q'))); .set("buzz", Box::new((1, 2.0, true, 'q')));
// This just makes me sad // This just makes me sad
qb.r#where("foo", "<>", Box::new(2)); qb.r#where("foo <>", Box::new(2));
println!("QueryBuilder object: {:#?}", &qb); println!("QueryBuilder object: {:#?}", &qb);

View File

@ -124,6 +124,14 @@ impl QueryBuilder {
self self
} }
/// Tell the database to give you query plain info, rather
/// than a result set
pub fn explain(&mut self) -> &mut Self {
self.state.explain = true;
self
}
/// Specify the database table to select from /// Specify the database table to select from
/// ///
/// ``` /// ```
@ -195,22 +203,31 @@ impl QueryBuilder {
// ! 'Where' methods // ! 'Where' methods
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
/// Specify a condition for the `where` clause of the query /// Alias method for `r#where`.
pub fn r#where(&mut self, key: &str, op: &str, value: Box<dyn Any>) -> &mut Self { pub fn filter(&mut self, key: &str, value: Box<dyn Any>) -> &mut Self {
// @TODO actually implement setting the keys for the where self.r#where(key, value)
self.state.append_where_values(value);
unimplemented!();
} }
/// Specify a condition for a `where` clause where a column has a value /// Specify a condition for the `where` clause of the query. Can be called
pub fn where_eq(&mut self, key: &str, value: Box<dyn Any>) -> &mut Self { /// multiple times, which will then add additional where conditions, prefixed
self.r#where(key, "=", value) /// with 'AND'.
///
/// ```no_run
/// # use stringqb::prelude::*;
/// # let mut qb = QueryBuilder::default();
/// // By default, key = value
/// qb.r#where("key", Box::new("value"));
///
/// // Other operators can be used with a separating space
/// qb.r#where("key >", Box::new(4));
/// ```
pub fn r#where(&mut self, key: &str, value: Box<dyn Any>) -> &mut Self {
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: Box<dyn Any>) -> &mut Self {
unimplemented!(); self._where_string(key, value, "OR")
} }
/// Specify a `where in` clause for the query /// Specify a `where in` clause for the query
@ -549,8 +566,38 @@ impl QueryBuilder {
self self
} }
fn _where_string(&mut self, key: &str, value: Box<dyn Any>) -> &mut Self { fn _where_string(&mut self, key: &str, value: Box<dyn Any>, conj: &str) -> &mut Self {
unimplemented!(); let keys = self._where(key, vec![value]);
for k in keys {
self._where_string_key(key, conj);
}
self
}
fn _where_string_key(&mut self, key: &str, conj: &str) {
let field = key.trim().split(" ").collect::<Vec<&str>>();
let query_map = self.state.get_query_map();
let last_item = &query_map[query_map.len() - 1];
let mut item = self.driver.quote_identifier(field[0]);
let item2 = if field.len() == 1 {
String::from("=?")
} else {
format!(" {} ?", &field[1])
};
item += &item2;
let conj = if last_item.clause_type == QueryClauseType::GroupStart {
String::from("")
} else {
format!(" {} ", conj)
};
self.state.append_query_map(QueryClauseType::Where, &conj, &item);
} }
fn compile(&self, query_type: QueryType, table: &str) -> String { fn compile(&self, query_type: QueryType, table: &str) -> String {
@ -570,11 +617,17 @@ impl QueryBuilder {
&parts.push(clause.to_string()); &parts.push(clause.to_string());
} }
let sql = parts.join(""); let mut sql = parts.join("");
// @TODO handle limit / offset // Add limit/ offset
sql = self.driver.limit(&sql, self.state.limit, self.state.offset);
sql // Handle explain
if self.state.explain == true {
self.driver.explain(&sql)
} else {
sql
}
} }
fn compile_type(&self, query_type: QueryType, table: &str) -> String { fn compile_type(&self, query_type: QueryType, table: &str) -> String {

View File

@ -2,7 +2,7 @@ use super::*;
#[derive(Debug)] #[derive(Debug)]
pub struct QueryClause { pub struct QueryClause {
clause_type: QueryClauseType, pub clause_type: QueryClauseType,
conjunction: String, conjunction: String,
string: String, string: String,
} }
@ -23,6 +23,8 @@ impl QueryClause {
#[derive(Debug)] #[derive(Debug)]
pub struct QueryState { pub struct QueryState {
pub explain: bool,
select_string: String, select_string: String,
from_string: String, from_string: String,
set_string: String, set_string: String,
@ -58,6 +60,8 @@ pub struct QueryState {
impl Default for QueryState { impl Default for QueryState {
fn default() -> Self { fn default() -> Self {
QueryState { QueryState {
explain: false,
select_string: String::from(""), select_string: String::from(""),
from_string: String::from(""), from_string: String::from(""),
set_string: String::from(""), set_string: String::from(""),