Implement more
This commit is contained in:
parent
f9979e9470
commit
0e1c6755b0
@ -4,16 +4,16 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[cfg(feature = "postgres")]
|
#[cfg(feature = "postgres")]
|
||||||
mod postgres;
|
pub mod postgres;
|
||||||
|
|
||||||
#[cfg(feature = "sqlite")]
|
#[cfg(feature = "sqlite")]
|
||||||
mod sqlite;
|
pub mod sqlite;
|
||||||
|
|
||||||
#[cfg(feature = "mysql")]
|
#[cfg(feature = "mysql")]
|
||||||
mod mysql;
|
pub mod mysql;
|
||||||
|
|
||||||
#[cfg(feature = "mssql")]
|
#[cfg(feature = "mssql")]
|
||||||
mod mssql;
|
pub mod mssql;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Connection;
|
struct Connection;
|
||||||
@ -22,12 +22,20 @@ struct Connection;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct QueryResult;
|
struct QueryResult;
|
||||||
|
|
||||||
struct DriverBase {
|
/// Empty Driver implementation
|
||||||
escape_char_open: char,
|
///
|
||||||
escape_char_close: char,
|
/// Good for general testing
|
||||||
has_truncate: bool,
|
#[derive(Debug)]
|
||||||
|
pub struct DefaultDriver;
|
||||||
|
|
||||||
|
impl DefaultDriver {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
DefaultDriver {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DatabaseDriver for DefaultDriver {}
|
||||||
|
|
||||||
/// Database Driver Trait
|
/// Database Driver Trait
|
||||||
///
|
///
|
||||||
/// Interface between the database connection library and the query builder
|
/// Interface between the database connection library and the query builder
|
||||||
@ -39,7 +47,7 @@ pub trait DatabaseDriver: fmt::Debug {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Vector version of `quote_identifier`
|
/// Vector version of `quote_identifier`
|
||||||
fn quote_identifiers<'a>(&self, identifiers: Vec<&'a str>) -> Vec<String> {
|
fn quote_identifiers(&self, identifiers: Vec<&str>) -> Vec<String> {
|
||||||
let mut output: Vec<String> = vec![];
|
let mut output: Vec<String> = vec![];
|
||||||
|
|
||||||
for identifier in identifiers {
|
for identifier in identifiers {
|
||||||
@ -81,7 +89,7 @@ pub trait DatabaseDriver: fmt::Debug {
|
|||||||
if tier.starts_with(open_char) && tier.ends_with(close_char) {
|
if tier.starts_with(open_char) && tier.ends_with(close_char) {
|
||||||
trimmed_tiers.push(tier.to_string());
|
trimmed_tiers.push(tier.to_string());
|
||||||
} else {
|
} else {
|
||||||
let mut tier = format!("{}{}{}", open_char, tier, close_char);
|
let tier = format!("{}{}{}", open_char, tier, close_char);
|
||||||
trimmed_tiers.push(tier.to_string());
|
trimmed_tiers.push(tier.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,26 +98,17 @@ pub trait DatabaseDriver: fmt::Debug {
|
|||||||
// @TODO Fix functional calls in 'select' queries
|
// @TODO Fix functional calls in 'select' queries
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs a basic sql query on the database
|
// Runs a basic sql query on the database
|
||||||
fn query(&self, query: &str) -> Result<(), ()>;
|
// fn query(&self, query: &str) -> Result<(), ()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct TestDriver;
|
|
||||||
|
|
||||||
impl DatabaseDriver for TestDriver {
|
|
||||||
fn query(&self, _query: &str) -> Result<(), ()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quote_identifier() {
|
fn test_quote_identifier() {
|
||||||
let driver = TestDriver {};
|
let driver = DefaultDriver::new();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
driver.quote_identifier("foo, bar, baz"),
|
driver.quote_identifier("foo, bar, baz"),
|
||||||
@ -123,7 +122,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quote_identifiers() {
|
fn test_quote_identifiers() {
|
||||||
let driver = TestDriver {};
|
let driver = DefaultDriver::new();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
driver.quote_identifiers(vec!["\tfoo. bar", "baz", "fizz.\n\tbuzz.baz",]),
|
driver.quote_identifiers(vec!["\tfoo. bar", "baz", "fizz.\n\tbuzz.baz",]),
|
||||||
|
@ -3,16 +3,18 @@ use super::*;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MSSQL;
|
pub struct MSSQL;
|
||||||
|
|
||||||
|
impl MSSQL {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
MSSQL {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl DatabaseDriver for MSSQL {
|
impl DatabaseDriver for MSSQL {
|
||||||
/// Get which characters are used to delimit identifiers
|
/// Get which characters are used to delimit identifiers
|
||||||
/// such as tables, and columns
|
/// such as tables, and columns
|
||||||
fn _quotes(&self) -> (char, char) {
|
fn _quotes(&self) -> (char, char) {
|
||||||
('[', ']')
|
('[', ']')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query(&self, _query: &str) -> Result<(), ()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -21,7 +23,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quote_identifier_bracket_quote() {
|
fn test_quote_identifier_bracket_quote() {
|
||||||
let driver = MSSQL {};
|
let driver = MSSQL::new();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
driver.quote_identifier("foo, bar, baz"),
|
driver.quote_identifier("foo, bar, baz"),
|
||||||
@ -35,7 +37,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quote_identifiers_bracket_quote() {
|
fn test_quote_identifiers_bracket_quote() {
|
||||||
let driver = MSSQL {};
|
let driver = MSSQL::new();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
driver.quote_identifiers(vec!["\tfoo. bar", "baz", "fizz.\n\tbuzz.baz",]),
|
driver.quote_identifiers(vec!["\tfoo. bar", "baz", "fizz.\n\tbuzz.baz",]),
|
||||||
|
@ -3,16 +3,18 @@ use super::*;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MySQL;
|
pub struct MySQL;
|
||||||
|
|
||||||
|
impl MySQL {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
MySQL {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl DatabaseDriver for MySQL {
|
impl DatabaseDriver for MySQL {
|
||||||
/// Get which characters are used to delimit identifiers
|
/// Get which characters are used to delimit identifiers
|
||||||
/// such as tables, and columns
|
/// such as tables, and columns
|
||||||
fn _quotes(&self) -> (char, char) {
|
fn _quotes(&self) -> (char, char) {
|
||||||
('`', '`')
|
('`', '`')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query(&self, _query: &str) -> Result<(), ()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -21,7 +23,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quote_identifier_backtick_quote() {
|
fn test_quote_identifier_backtick_quote() {
|
||||||
let driver = MySQL {};
|
let driver = MySQL::new();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
driver.quote_identifier("foo, bar, baz"),
|
driver.quote_identifier("foo, bar, baz"),
|
||||||
@ -35,7 +37,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_quote_identifiers_backtick_quote() {
|
fn test_quote_identifiers_backtick_quote() {
|
||||||
let driver = MySQL {};
|
let driver = MySQL::new();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
driver.quote_identifiers(vec!["\tfoo. bar", "baz", "fizz.\n\tbuzz.baz",]),
|
driver.quote_identifiers(vec!["\tfoo. bar", "baz", "fizz.\n\tbuzz.baz",]),
|
||||||
|
@ -3,8 +3,10 @@ use super::*;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Postgres;
|
pub struct Postgres;
|
||||||
|
|
||||||
impl DatabaseDriver for Postgres {
|
impl Postgres {
|
||||||
fn query(&self, _query: &str) -> Result<(), ()> {
|
pub fn new() -> Self {
|
||||||
Ok(())
|
Postgres {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DatabaseDriver for Postgres { }
|
||||||
|
@ -3,12 +3,10 @@ use super::*;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SQLite;
|
pub struct SQLite;
|
||||||
|
|
||||||
impl DatabaseDriver for SQLite {
|
impl SQLite {
|
||||||
fn quote_identifier(&self, identifier: &str) -> String {
|
pub fn new() -> Self {
|
||||||
String::from(identifier)
|
SQLite {}
|
||||||
}
|
|
||||||
|
|
||||||
fn query(&self, _query: &str) -> Result<(), ()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DatabaseDriver for SQLite { }
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
//! This main file is just for temparary testing
|
//! This main file is just for temparary testing
|
||||||
use stringqb::query_builder::QueryBuilder;
|
use stringqb::query_builder::QueryBuilder;
|
||||||
use stringqb::types::{SQLType, Type};
|
use stringqb::types::{SQLType, Type};
|
||||||
|
use stringqb::drivers::postgres::Postgres;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut qb = QueryBuilder::new();
|
let mut qb = QueryBuilder::new(Postgres::new());
|
||||||
|
|
||||||
qb.set("foo", Box::new("bar"))
|
qb.set("foo", Box::new("bar"))
|
||||||
.set("bar", Box::new(12))
|
.set("bar", Box::new(12))
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::drivers::DatabaseDriver;
|
use crate::drivers::{ DatabaseDriver, DefaultDriver };
|
||||||
|
|
||||||
/// The position of the wildcard(s)
|
/// The position of the wildcard(s)
|
||||||
/// for a `like` clause
|
/// for a `like` clause
|
||||||
@ -35,21 +35,22 @@ pub enum JoinType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The sort direction
|
/// The sort direction
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum OrderDirection {
|
pub enum OrderDirection {
|
||||||
/// Sort Ascending
|
/// Sort Ascending
|
||||||
Asc,
|
Asc,
|
||||||
/// Sort Descending
|
/// Sort Descending
|
||||||
Desc,
|
Desc,
|
||||||
|
/// Random Sort
|
||||||
|
Rand,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum QueryClauseType {
|
enum QueryClauseType {
|
||||||
AndGroupStart,
|
|
||||||
GroupEnd,
|
GroupEnd,
|
||||||
GroupStart,
|
GroupStart,
|
||||||
|
Join,
|
||||||
Like,
|
Like,
|
||||||
OrGroupStart,
|
|
||||||
Where,
|
Where,
|
||||||
WhereIn,
|
WhereIn,
|
||||||
}
|
}
|
||||||
@ -62,11 +63,11 @@ struct QueryClause {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl QueryClause {
|
impl QueryClause {
|
||||||
pub fn new(clause_type: QueryClauseType, conjunction: String, string: String) -> Self {
|
pub fn new(clause_type: QueryClauseType, conjunction: &str, string: &str) -> Self {
|
||||||
QueryClause {
|
QueryClause {
|
||||||
clause_type,
|
clause_type,
|
||||||
conjunction,
|
conjunction: conjunction.to_string(),
|
||||||
string,
|
string: string.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,7 +87,7 @@ struct QueryState {
|
|||||||
order_array: HashMap<String, String>,
|
order_array: HashMap<String, String>,
|
||||||
|
|
||||||
// Group by clause
|
// Group by clause
|
||||||
group_array: HashMap<String, String>,
|
group_array: Vec<String>,
|
||||||
|
|
||||||
// Values to apply to prepared statements
|
// Values to apply to prepared statements
|
||||||
values: Vec<Box<dyn Any>>,
|
values: Vec<Box<dyn Any>>,
|
||||||
@ -116,7 +117,7 @@ impl Default for QueryState {
|
|||||||
|
|
||||||
set_array_keys: vec![],
|
set_array_keys: vec![],
|
||||||
order_array: HashMap::new(),
|
order_array: HashMap::new(),
|
||||||
group_array: HashMap::new(),
|
group_array: vec![],
|
||||||
values: vec![],
|
values: vec![],
|
||||||
where_values: vec![],
|
where_values: vec![],
|
||||||
|
|
||||||
@ -133,21 +134,43 @@ impl QueryState {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
QueryState::default()
|
QueryState::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn append_select_string(&mut self, s:&str) -> &mut Self {
|
||||||
|
self.select_string += 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(Default, Debug)]
|
#[derive(Debug)]
|
||||||
pub struct QueryBuilder {
|
pub struct QueryBuilder {
|
||||||
state: QueryState,
|
state: QueryState,
|
||||||
driver: Option<Box<dyn DatabaseDriver>>,
|
driver: Box<dyn DatabaseDriver>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for QueryBuilder {
|
||||||
|
/// Creates a new QueryBuilder instance with default driver
|
||||||
|
fn default() -> Self {
|
||||||
|
QueryBuilder {
|
||||||
|
state: QueryState::new(),
|
||||||
|
driver: Box::new(DefaultDriver::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QueryBuilder {
|
impl QueryBuilder {
|
||||||
/// Creates a new QueryBuilder instance
|
/// Create a new QueryBuilder instance with a driver
|
||||||
pub fn new() -> Self {
|
pub fn new(driver: impl DatabaseDriver + 'static) -> Self {
|
||||||
QueryBuilder {
|
QueryBuilder {
|
||||||
state: QueryState::new(),
|
state: QueryState::new(),
|
||||||
driver: None,
|
driver: Box::new(driver),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,19 +319,82 @@ impl QueryBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convenience method for a `left` join
|
||||||
|
pub fn left_join(&mut self, table: &str, col: &str, op: &str, value: &str) -> &mut Self {
|
||||||
|
self.join(table, col, op, value, JoinType::Left)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience method for an `inner` join
|
||||||
|
pub fn inner_join(&mut self, table: &str, col: &str, op: &str, value: &str) -> &mut Self {
|
||||||
|
self.join(table, col, op, value, JoinType::Inner)
|
||||||
|
}
|
||||||
|
|
||||||
/// Add a table join to the query
|
/// Add a table join to the query
|
||||||
pub fn join(&mut self, table: &str, condition: &str, join_type: JoinType) -> &mut Self {
|
pub fn join(&mut self, table: &str, col: &str, op: &str, value: &str, join_type: JoinType) -> &mut Self {
|
||||||
unimplemented!();
|
let table = self.driver.quote_identifier(table);
|
||||||
|
let col = self.driver.quote_identifier(col);
|
||||||
|
let condition = table + " ON " + &col + op + value;
|
||||||
|
|
||||||
|
let join_type = match join_type {
|
||||||
|
JoinType::Left => "LEFT ",
|
||||||
|
JoinType::Inner => "INNER ",
|
||||||
|
JoinType::LeftOuter => "LEFT OUTER ",
|
||||||
|
JoinType::Outer => "OUTER ",
|
||||||
|
JoinType::Right => "RIGHT ",
|
||||||
|
JoinType::RightOuter => "RIGHT OUTER",
|
||||||
|
};
|
||||||
|
|
||||||
|
let conjunction = "\n".to_string() + join_type + "JOIN ";
|
||||||
|
|
||||||
|
self.state.query_map.push(QueryClause::new(
|
||||||
|
QueryClauseType::Join,
|
||||||
|
&conjunction,
|
||||||
|
&condition
|
||||||
|
));
|
||||||
|
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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 {
|
||||||
unimplemented!();
|
self.state.group_array.push(field.to_string());
|
||||||
|
|
||||||
|
self.state.group_string = " GROUP BY ".to_string() + &self.state.group_array.join(",");
|
||||||
|
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add an order by clause to the query
|
/// Add an order by clause to the query
|
||||||
pub fn order_by(&mut self, field: &str, direction: OrderDirection) -> &mut Self {
|
pub fn order_by(&mut self, field: &str, direction: OrderDirection) -> &mut Self {
|
||||||
unimplemented!();
|
if direction == OrderDirection::Rand {
|
||||||
|
// @TODO handle random sorting
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
let field = self.driver.quote_identifier(field);
|
||||||
|
let dir = match direction {
|
||||||
|
OrderDirection::Asc => String::from("ASC"),
|
||||||
|
OrderDirection::Desc => String::from("DESC"),
|
||||||
|
OrderDirection::Rand => String::from("RAND"),
|
||||||
|
};
|
||||||
|
self.state.order_array.insert(field, dir);
|
||||||
|
|
||||||
|
let mut order_clauses: Vec<String> = vec![];
|
||||||
|
|
||||||
|
for (f, dir) in &self.state.order_array {
|
||||||
|
let clause = String::clone(f) + " " + &dir;
|
||||||
|
&order_clauses.push(clause);
|
||||||
|
}
|
||||||
|
|
||||||
|
let order_str = if direction != OrderDirection::Rand {
|
||||||
|
"\nORDER BY ".to_string() + &order_clauses.join(", ")
|
||||||
|
} else {
|
||||||
|
unimplemented!();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.state.order_string = order_str;
|
||||||
|
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a limit to the query
|
/// Add a limit to the query
|
||||||
@ -331,27 +417,73 @@ 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 {
|
||||||
unimplemented!();
|
if self.state.query_map.len() == 0 {
|
||||||
|
self.state.query_map.push(QueryClause::new(
|
||||||
|
QueryClauseType::GroupStart,
|
||||||
|
" ",
|
||||||
|
"("
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
self.state.query_map.push(QueryClause::new(
|
||||||
|
QueryClauseType::GroupStart,
|
||||||
|
" WHERE ",
|
||||||
|
"("
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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 {
|
||||||
unimplemented!();
|
if self.state.query_map.len() == 0 {
|
||||||
|
self.state.query_map.push(QueryClause::new(
|
||||||
|
QueryClauseType::GroupStart,
|
||||||
|
" WHERE ",
|
||||||
|
"("
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
self.state.query_map.push(QueryClause::new(
|
||||||
|
QueryClauseType::GroupStart,
|
||||||
|
" AND ",
|
||||||
|
"("
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start a logical grouping, prefixed with `or`
|
/// Start a logical grouping, prefixed with `or`
|
||||||
pub fn or_group_start(&mut self) -> &mut Self {
|
pub fn or_group_start(&mut self) -> &mut Self {
|
||||||
unimplemented!();
|
self.state.query_map.push(QueryClause::new(
|
||||||
|
QueryClauseType::GroupStart,
|
||||||
|
"",
|
||||||
|
" OR ("
|
||||||
|
));
|
||||||
|
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start a logical grouping, prefixed with `or not`
|
/// Start a logical grouping, prefixed with `or not`
|
||||||
pub fn or_not_group_start(&mut self) -> &mut Self {
|
pub fn or_not_group_start(&mut self) -> &mut Self {
|
||||||
unimplemented!();
|
self.state.query_map.push(QueryClause::new(
|
||||||
|
QueryClauseType::GroupStart,
|
||||||
|
"",
|
||||||
|
" OR NOT ("
|
||||||
|
));
|
||||||
|
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// End the current logical grouping
|
/// End the current logical grouping
|
||||||
pub fn group_end(&mut self) -> &mut Self {
|
pub fn group_end(&mut self) -> &mut Self {
|
||||||
unimplemented!();
|
self.state.query_map.push(QueryClause::new(
|
||||||
|
QueryClauseType::GroupEnd,
|
||||||
|
"",
|
||||||
|
")"
|
||||||
|
));
|
||||||
|
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@ -414,8 +546,10 @@ 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_query(mut self) -> Self {
|
||||||
QueryBuilder::new()
|
self.state = QueryState::new();
|
||||||
|
|
||||||
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,7 +559,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_key_value() {
|
fn set_key_value() {
|
||||||
let mut qb = QueryBuilder::new();
|
let mut qb = QueryBuilder::default();
|
||||||
|
|
||||||
qb.set("foo", Box::new("bar"));
|
qb.set("foo", Box::new("bar"));
|
||||||
|
|
||||||
@ -438,7 +572,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_hashmap() {
|
fn set_hashmap() {
|
||||||
let mut qb = QueryBuilder::new();
|
let mut qb = QueryBuilder::default();
|
||||||
|
|
||||||
let mut authors: HashMap<String, Box<dyn Any>> = HashMap::new();
|
let mut authors: HashMap<String, Box<dyn Any>> = HashMap::new();
|
||||||
authors.insert(
|
authors.insert(
|
||||||
|
Loading…
Reference in New Issue
Block a user