prgress commit

This commit is contained in:
Timothy Warren 2019-04-22 08:59:40 -04:00
parent 4262b5b1c0
commit 861069abe7
7 changed files with 67 additions and 23 deletions

View File

@ -12,8 +12,7 @@ regex = "1.1.5"
serde_json = "1.0.39"
[dependencies.pg]
version="0.15.2"
features=["with-serde_json"]
version="0.16.0-rc.1"
optional=true
package="postgres"

View File

@ -3,7 +3,8 @@
//! Drivers represent a connection to a specific type of database engine
use crate::fns::split_map_join;
use regex::Regex;
use std::fmt;
use std::any::Any;
use std::error::Error;
#[cfg(feature = "postgres")]
pub mod postgres;
@ -50,7 +51,7 @@ impl DatabaseDriver for DefaultDriver {
/// Database Driver Trait
///
/// Interface between the database connection library and the query builder
pub trait DatabaseDriver: fmt::Debug {
pub trait DatabaseDriver {
/// Get which characters are used to delimit identifiers
/// such as tables, and columns
fn _quotes(&self) -> (char, char) {
@ -103,7 +104,10 @@ pub trait DatabaseDriver: fmt::Debug {
}
// Runs a basic sql query on the database
// fn query(&self, query: &str) -> Result<(), ()>;
// fn query(&self, sql: &str) -> Result<impl Any, impl Error>;
// Runs a prepared statement on the database
// fn execute(&self, sql: &str, ?) -> Result<?,?>
// ------------------------------------------------------------------------
// ! Driver-specific SQL methods

View File

@ -1,5 +1,7 @@
//! Database Driver for MySQL
//!
//! Use of this driver requires enabling the `mysql` feature.
//!
//! Contains database-specific query data
use super::*;

View File

@ -1,16 +1,49 @@
//! Database Driver for Postgres
//!
//! Contains database-specific query data
//! Use of this driver requires enabling the `postgres` feature. The `postgres`
//! feature is enabled by default.
//!
//! Uses the [Postgres](https://crates.io/crates/postgres) crate for
//! interfacing with the database
use super::*;
use pg::{Client, Error, NoTls, Row};
use std::any::Any;
use std::cell::RefCell;
/// The struct implementing the `DatabaseDriver` trait
#[derive(Debug)]
pub struct PostgresDriver;
pub struct PostgresDriver {
connection: RefCell<Option<Client>>,
}
impl PostgresDriver {
/// Create a PostgresDriver driver
pub fn new() -> Self {
PostgresDriver {}
pub fn new(dsn: &str) -> Self {
let mut driver = PostgresDriver {
connection: RefCell::new(None),
};
driver.connect(dsn);
driver
}
fn connect(&mut self, dsn: &str) {
let connection = Client::connect(dsn, NoTls).unwrap();
self.connection = RefCell::new(Some(connection));
}
pub fn query(&self, sql: &str) -> Result<Vec<Row>, Error> {
if self.connection.borrow().is_none() {
panic!("No database connection.");
}
self.connection
.borrow_mut()
.as_mut()
.unwrap()
.query(sql, &[])
}
}

View File

@ -2,11 +2,19 @@
//!
//! A query builder using mostly strings, with methods following common SQL syntax
//!
//! ```
//!
//! ```no_run
//! use stringqb::prelude::*;
//!
//! // Create a QueryBuilder object, with the chosen database driver
//! let qb = QueryBuilder::new(PostgresDriver::new("postgresql://user@localhost"));
//!
//! ```
//!
//! Drivers include:
//! * `PostgresDriver` - for PostgreSQL databases
//! * `MySQLDriver` - for MySQL/MariaDB databases
//! * `SQLiteDriver` - for SQLite databases
#![warn(missing_docs)]
#[macro_use]

View File

@ -80,7 +80,6 @@ enum QueryType {
}
/// The struct representing a query builder
#[derive(Debug)]
pub struct QueryBuilder {
/// The struct to store the query builder info
state: QueryState,
@ -207,7 +206,7 @@ impl QueryBuilder {
// ! 'Like' methods
// --------------------------------------------------------------------------
/// Creates a `like` clause in the sql statement
/// Creates a `like` clause in the sql
///
/// ```no_run
/// # use stringqb::prelude::*;
@ -225,12 +224,12 @@ impl QueryBuilder {
self._like(field, value, position, "LIKE", "AND")
}
/// Generates an OR Like clause
/// Generates an `or like` clause
pub fn or_like(&mut self, field: &str, value: impl Any, position: LikeWildcard) -> &mut Self {
self._like(field, value, position, "LIKE", "OR")
}
/// Generates a NOI Like clause
/// Generates a `not like` clause
pub fn not_like(&mut self, field: &str, value: impl Any, position: LikeWildcard) -> &mut Self {
self._like(field, value, position, "NOT LIKE", "AND")
}
@ -255,10 +254,10 @@ impl QueryBuilder {
/// # use stringqb::prelude::*;
/// # let mut qb = QueryBuilder::default();
/// // By default, key = value
/// qb.having("key", vec![Box::new("value")]);
/// qb.having("key", vec!["value"]);
///
/// // Other operators can be used with a separating space
/// qb.having("clues >=", vec![Box::new(4)]);
/// qb.having("clues >=", vec![4]);
/// ```
pub fn having(&mut self, key: &str, value: Vec<impl Any>) -> &mut Self {
self._having(key, value, "AND")
@ -281,10 +280,10 @@ impl QueryBuilder {
/// # use stringqb::prelude::*;
/// # let mut qb = QueryBuilder::default();
/// // By default, key = value
/// qb.r#where("key", Box::new("value"));
/// qb.r#where("key", "value");
///
/// // Other operators can be used with a separating space
/// qb.r#where("key >", Box::new(4));
/// qb.r#where("key >", 4);
/// ```
pub fn r#where(&mut self, key: &str, value: impl Any) -> &mut Self {
self._where_string(key, value, "AND")
@ -681,7 +680,7 @@ impl QueryBuilder {
match last_item.clause_type {
QueryClauseType::GroupStart => String::from(""),
_ => format!(" {} ", conj)
_ => format!(" {} ", conj),
}
} else {
format!(" {} ", conj)
@ -939,7 +938,7 @@ impl QueryState {
pub fn get_query_map_last(&self) -> Option<&QueryClause> {
if self.query_map.len() == 0 {
return None
return None;
}
let index = self.query_map.len() - 1;

View File

@ -51,8 +51,7 @@ fn select_without_from() {
fn select_where() {
let mut qb = QueryBuilder::default();
qb.from("test")
.r#where("foo", "bar");
qb.from("test").r#where("foo", "bar");
let sql = qb.get_compiled_select();
let expected = "SELECT *\nFROM \"test\" WHERE \"foo\"=?";