Another progress commit

This commit is contained in:
Timothy Warren 2019-04-04 16:39:05 -04:00
parent 80f85b6579
commit 3865fd56b2
7 changed files with 96 additions and 79 deletions

View File

@ -3,16 +3,15 @@
//! Drivers represent a connection to a specific type of database engine //! Drivers represent a connection to a specific type of database engine
use std::fmt; use std::fmt;
#[cfg(feature="postgres")] #[cfg(feature = "postgres")]
mod postgres; mod postgres;
#[cfg(feature="sqlite")] #[cfg(feature = "sqlite")]
mod sqlite; mod sqlite;
#[cfg(feature="mysql")] #[cfg(feature = "mysql")]
mod mysql; mod mysql;
#[derive(Debug)] #[derive(Debug)]
struct Connection; struct Connection;
@ -20,6 +19,11 @@ struct Connection;
#[derive(Debug)] #[derive(Debug)]
struct QueryResult; struct QueryResult;
struct DriverBase {
escape_char_open: char,
escape_char_close: char,
has_truncate: bool,
}
/// Database Driver Trait /// Database Driver Trait
/// ///

View File

@ -3,7 +3,6 @@ use super::*;
#[derive(Debug)] #[derive(Debug)]
pub struct Postgres; pub struct Postgres;
#[cfg(feature="pg")]
impl DatabaseDriver for Postgres { impl DatabaseDriver for Postgres {
fn quote_identifier(&self, identifier: &str) -> String { fn quote_identifier(&self, identifier: &str) -> String {
String::from(identifier) String::from(identifier)
@ -12,4 +11,4 @@ impl DatabaseDriver for Postgres {
fn query(&self, _query: &str) -> Result<(), ()> { fn query(&self, _query: &str) -> Result<(), ()> {
Ok(()) Ok(())
} }
} }

View File

@ -11,4 +11,4 @@ impl DatabaseDriver for SQLite {
fn query(&self, _query: &str) -> Result<(), ()> { fn query(&self, _query: &str) -> Result<(), ()> {
Ok(()) Ok(())
} }
} }

View File

@ -1,9 +1,8 @@
//! # 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
#![warn(missing_docs)] // #![warn(missing_docs)]
pub mod drivers; pub mod drivers;
pub mod query_builder; pub mod query_builder;
pub mod types; pub mod types;

View File

@ -3,20 +3,19 @@ use stringqb::query_builder::QueryBuilder;
use stringqb::types::{SQLType, Type}; use stringqb::types::{SQLType, Type};
fn main() { fn main() {
let qb = QueryBuilder::new() let mut qb = QueryBuilder::new();
.set("foo", Box::new("bar"))
.set("bar", Box::new(12)) qb.set("foo", Box::new("bar"))
.set("baz", Box::new(false)) .set("bar", Box::new(12))
.set("fizz", Box::new(12.38)) .set("baz", Box::new(false))
.set("buzz", Box::new((1, 2.0, true, 'q'))); .set("fizz", Box::new(12.38))
.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));
let qb = qb.r#where("foo", Box::new(2));
println!("QueryBuilder object: {:#?}", &qb);
println!("QueryBuilder object: {:#?}", &qb);
println!("SQLType mapping: {:#?}", SQLType::SmallInt(32));
println!("SQLType mapping: {:#?}", SQLType::SmallInt(32)); println!("Type: {:#?}", Type(Box::new(1234567890)));
println!("Type: {:#?}", Type(Box::new(1234567890)));
} }

View File

@ -94,9 +94,9 @@ struct QueryState {
// Values to apply to where clauses in prepared statements // Values to apply to where clauses in prepared statements
where_values: Vec<Box<dyn Any>>, where_values: Vec<Box<dyn Any>>,
limit: Option<u32>, limit: Option<usize>,
offset: Option<u32>, offset: Option<usize>,
// Query components for complex selects // Query components for complex selects
query_map: Vec<QueryClause>, query_map: Vec<QueryClause>,
@ -130,7 +130,7 @@ impl Default for QueryState {
} }
impl QueryState { impl QueryState {
pub fn new() -> QueryState { pub fn new() -> Self {
QueryState::default() QueryState::default()
} }
} }
@ -156,17 +156,17 @@ impl QueryBuilder {
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
/// Set the fields to select from the database /// Set the fields to select from the database
pub fn select(mut self, fields: &str) -> Self { pub fn select(&mut self, fields: &str) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// Adds the `distinct` keyword to a query /// Adds the `distinct` keyword to a query
pub fn distinct(mut self) -> Self { pub fn distinct(&mut self) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// Specify the database table to select from /// Specify the database table to select from
pub fn from(mut self, table_name: &str) -> Self { pub fn from(&mut self, table_name: &str) -> &mut Self {
// @TODO properly escape the table name // @TODO properly escape the table name
self.state.from_string = table_name.to_string(); self.state.from_string = table_name.to_string();
@ -178,22 +178,37 @@ impl QueryBuilder {
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
/// Creates a `like` clause in the sql statement /// Creates a `like` clause in the sql statement
pub fn like(mut self, field: &str, value: Box<dyn Any>, position: LikeWildcard) -> Self { pub fn like(&mut self, field: &str, value: Box<dyn Any>, position: LikeWildcard) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// Generates an OR Like clause /// Generates an OR Like clause
pub fn or_like(mut self, field: &str, value: Box<dyn Any>, position: LikeWildcard) -> Self { pub fn or_like(
&mut self,
field: &str,
value: Box<dyn Any>,
position: LikeWildcard,
) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// Generates a NOI Like clause /// Generates a NOI Like clause
pub fn not_like(mut self, field: &str, value: Box<dyn Any>, position: LikeWildcard) -> Self { pub fn not_like(
&mut self,
field: &str,
value: Box<dyn Any>,
position: LikeWildcard,
) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// Generates an OR NOT Like clause /// Generates an OR NOT Like clause
pub fn or_not_like(mut self, field: &str, value: Box<dyn Any>, position: LikeWildcard) -> Self { pub fn or_not_like(
&mut self,
field: &str,
value: Box<dyn Any>,
position: LikeWildcard,
) -> &mut Self {
unimplemented!(); unimplemented!();
} }
@ -202,12 +217,12 @@ impl QueryBuilder {
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
/// Add a `having` clause to the query /// Add a `having` clause to the query
pub fn having(mut self, key:&str, value: Box<dyn Any>) -> Self { pub fn having(&mut self, key: &str, value: Box<dyn Any>) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// 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: Box<dyn Any>) -> Self { pub fn or_having(&mut self, key: &str, value: Box<dyn Any>) -> &mut Self {
unimplemented!(); unimplemented!();
} }
@ -216,35 +231,35 @@ 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, value: Box<dyn Any>) -> Self { pub fn r#where(&mut self, key: &str, value: Box<dyn Any>) -> &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.where_values.push(value);
self self
} }
/// 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>) -> Self { pub fn or_where(&mut self, key: &str, value: Box<dyn Any>) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// Specify a `where in` clause for the query /// Specify a `where in` clause for the query
pub fn where_in(mut self, key: &str, value: Vec<Box<dyn Any>>) -> Self { pub fn where_in(&mut self, key: &str, value: Vec<Box<dyn Any>>) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// 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, value: Vec<Box<dyn Any>>) -> Self { pub fn or_where_in(&mut self, key: &str, value: Vec<Box<dyn Any>>) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// 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, value: Vec<Box<dyn Any>>) -> Self { pub fn where_not_in(&mut self, key: &str, value: Vec<Box<dyn Any>>) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// 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, value: Vec<Box<dyn Any>>) -> Self { pub fn or_where_not_in(&mut self, key: &str, value: Vec<Box<dyn Any>>) -> &mut Self {
unimplemented!(); unimplemented!();
} }
@ -253,7 +268,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: Box<dyn Any>) -> Self { pub fn set(&mut self, key: &str, value: Box<dyn Any>) -> &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.set_array_keys.push(key.to_string());
self.state.values.push(value); self.state.values.push(value);
@ -262,38 +277,38 @@ impl QueryBuilder {
} }
/// 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>>) -> Self { pub fn set_map(&mut self, data: HashMap<String, Box<dyn Any>>) -> &mut Self {
for (key, value) in data { for (key, value) in data {
self = self.set(&key, value); self.set(&key, value);
} }
self self
} }
/// 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) -> Self { pub fn join(&mut self, table: &str, condition: &str, join_type: JoinType) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// Add a group by clause to the query /// Add a group by clause to the query
pub fn group_by(mut self, field: &str) -> Self { pub fn group_by(&mut self, field: &str) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// 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) -> Self { pub fn order_by(&mut self, field: &str, direction: OrderDirection) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// Add a limit to the query /// Add a limit to the query
pub fn limit(mut self, limit: u32) -> Self { pub fn limit(&mut self, limit: usize) -> &mut Self {
self.state.limit = Some(limit); self.state.limit = Some(limit);
self self
} }
/// Add an offset to the query /// Add an offset to the query
pub fn offset(mut self, offset: u32) -> Self { pub fn offset(&mut self, offset: usize) -> &mut Self {
self.state.offset = Some(offset); self.state.offset = Some(offset);
self self
@ -304,27 +319,27 @@ impl QueryBuilder {
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
/// Start a logical grouping in the current query /// Start a logical grouping in the current query
pub fn group_start(mut self) -> Self { pub fn group_start(&mut self) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// Start a logical grouping, prefixed with `not` /// Start a logical grouping, prefixed with `not`
pub fn not_group_start(mut self) -> Self { pub fn not_group_start(&mut self) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// Start a logical grouping, prefixed with `or` /// Start a logical grouping, prefixed with `or`
pub fn or_group_start(mut self) -> Self { pub fn or_group_start(&mut self) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// Start a logical grouping, prefixed with `or not` /// Start a logical grouping, prefixed with `or not`
pub fn or_not_group_start(mut self) -> Self { pub fn or_not_group_start(&mut self) -> &mut Self {
unimplemented!(); unimplemented!();
} }
/// End the current logical grouping /// End the current logical grouping
pub fn group_end(mut self) -> Self { pub fn group_end(&mut self) -> &mut Self {
unimplemented!(); unimplemented!();
} }
@ -338,24 +353,24 @@ impl QueryBuilder {
} }
/// Count all the rows in the specified database table /// Count all the rows in the specified database table
pub fn count_all(self, table: &str) -> u32 { pub fn count_all(self, table: &str) -> usize {
unimplemented!(); unimplemented!();
} }
/// Execute the generated insert query /// Execute the generated insert query
pub fn insert(mut self, table: &str) { pub fn insert(&mut self, table: &str) {
// @TODO determine query result type // @TODO determine query result type
unimplemented!(); unimplemented!();
} }
/// Execute the generated update query /// Execute the generated update query
pub fn update(mut self, table: &str) { pub fn update(&mut self, table: &str) {
// @TODO determine query result type // @TODO determine query result type
unimplemented!(); unimplemented!();
} }
/// Execute the generated delete query /// Execute the generated delete query
pub fn delete(mut self, table: &str) { pub fn delete(&mut self, table: &str) {
unimplemented!(); unimplemented!();
} }
@ -388,7 +403,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_query(&mut self) -> Self {
QueryBuilder::new() QueryBuilder::new()
} }
} }
@ -399,8 +414,9 @@ mod tests {
#[test] #[test]
fn set_key_value() { fn set_key_value() {
let qb = QueryBuilder::new() let mut qb = QueryBuilder::new();
.set("foo", Box::new("bar"));
qb.set("foo", Box::new("bar"));
assert_eq!(qb.state.set_array_keys[0], "foo"); assert_eq!(qb.state.set_array_keys[0], "foo");
assert!(qb.state.values[0].is::<&str>()); assert!(qb.state.values[0].is::<&str>());
@ -411,20 +427,20 @@ mod tests {
#[test] #[test]
fn set_hashmap() { fn set_hashmap() {
let qb = QueryBuilder::new(); let mut qb = QueryBuilder::new();
let mut authors: HashMap<String, Box<dyn Any>> = HashMap::new(); let mut authors: HashMap<String, Box<dyn Any>> = HashMap::new();
authors.insert( authors.insert(
String::from("Chinua Achebe"), String::from("Chinua Achebe"),
Box::new(String::from("Nigeria"))); Box::new(String::from("Nigeria")),
);
authors.insert( authors.insert(
String::from("Rabindranath Tagore"), String::from("Rabindranath Tagore"),
Box::new(String::from("India"))); Box::new(String::from("India")),
authors.insert( );
String::from("Anita Nair"), authors.insert(String::from("Anita Nair"), Box::new(String::from("India")));
Box::new(String::from("India")));
let qb = 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.set_array_keys.len(), 3);

View File

@ -7,21 +7,21 @@ pub struct Type(pub Box<dyn Any>);
/// Enum struct for mapping between database and Rust types /// Enum struct for mapping between database and Rust types
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub enum SQLType<T> { pub enum SQLType<T> {
Boolean(T), Boolean(T),
SmallInt(T), SmallInt(T),
BigInt(T), BigInt(T),
Text(T), Text(T),
None, None,
} }
impl<T> SQLType<T> { impl<T> SQLType<T> {
pub fn is_some(&self) -> bool { pub fn is_some(&self) -> bool {
match *self { match *self {
SQLType::None => false, SQLType::None => false,
_ => true, _ => true,
} }
} }
pub fn is_none(&self) -> bool { pub fn is_none(&self) -> bool {
!self.is_some() !self.is_some()
} }