Ugly progress commit
This commit is contained in:
parent
f9569a6340
commit
aad53f0f20
@ -72,7 +72,7 @@ pub trait DatabaseDriver {
|
||||
/// Quote the identifiers passed, so the database does not
|
||||
/// normalize the identifiers (eg, table, column, etc.)
|
||||
fn quote_identifier(&self, identifier: &str) -> String {
|
||||
let identifier = &mut String::from(identifier);
|
||||
let mut identifier = &mut String::from(identifier);
|
||||
|
||||
// If the identifier is actually a comma-separated list,
|
||||
// recurse to quote each identifier in the list
|
||||
@ -104,7 +104,7 @@ pub trait DatabaseDriver {
|
||||
// Runs a basic sql query on the database
|
||||
// fn query(&self, sql: &str) -> Result<impl Any, impl Error>;
|
||||
|
||||
// Prepares an sql statement for the database
|
||||
/// Prepares an sql statement for the database
|
||||
fn prepare(&self, sql: &str) -> Result<(), ()> {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -2,7 +2,8 @@
|
||||
//!
|
||||
//! Use of this driver requires enabling the `sqlite` feature.
|
||||
//!
|
||||
//! Contains database-specific query data
|
||||
//! Uses the [rusqlite](https://crates.io/crates/rusqlite) crate for
|
||||
//! interfacing with the database
|
||||
use super::*;
|
||||
|
||||
use slite::NO_PARAMS;
|
||||
@ -36,6 +37,18 @@ impl SQLiteDriver {
|
||||
|
||||
self.connection = RefCell::new(Some(connection));
|
||||
}
|
||||
|
||||
pub fn query(&self, sql: &str) -> Result<usize> {
|
||||
if self.connection.borrow().is_none() {
|
||||
panic!("No database connection.");
|
||||
}
|
||||
|
||||
self.connection
|
||||
.borrow_mut()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.execute(sql, NO_PARAMS)
|
||||
}
|
||||
}
|
||||
|
||||
impl DatabaseDriver for SQLiteDriver {
|
||||
|
11
src/lib.rs
11
src/lib.rs
@ -20,6 +20,10 @@
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
#[macro_use]
|
||||
extern crate slite;
|
||||
|
||||
pub mod drivers;
|
||||
pub mod fns;
|
||||
pub mod query_builder;
|
||||
@ -31,7 +35,12 @@ pub mod prelude {
|
||||
//! This includes enum types, traits,
|
||||
//! the Query Builder, and individual database drivers.
|
||||
pub use crate::drivers::DatabaseDriver;
|
||||
pub use crate::query_builder::{JoinType, LikeWildcard, OrderDirection, QueryBuilder};
|
||||
pub use crate::query_builder::{
|
||||
JoinType,
|
||||
LikeWildcard,
|
||||
OrderDirection,
|
||||
QueryBuilder,
|
||||
};
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
/// Postgres Driver
|
||||
|
@ -86,6 +86,11 @@ pub struct QueryBuilder {
|
||||
driver: Box<dyn DatabaseDriver>,
|
||||
}
|
||||
|
||||
/// The struct representing a prepared statement
|
||||
pub struct Prepared {
|
||||
|
||||
}
|
||||
|
||||
impl Default for QueryBuilder {
|
||||
/// Creates a new QueryBuilder instance with default driver
|
||||
///
|
||||
@ -179,7 +184,7 @@ impl QueryBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Tell the database to give you query plain info, rather
|
||||
/// Tell the database to give you query plan info, rather
|
||||
/// than a result set
|
||||
pub fn explain(&mut self) -> &mut Self {
|
||||
self.state.explain = true;
|
||||
@ -225,16 +230,55 @@ impl QueryBuilder {
|
||||
}
|
||||
|
||||
/// Generates an `or like` clause
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = stringqb::query_builder::QueryBuilder::default();
|
||||
/// // Search for a value that ends with "foo"
|
||||
/// qb.or_like("field", String::from("foo"), LikeWildcard::Before);
|
||||
///
|
||||
/// // Search for a value that starts with "foo"
|
||||
/// qb.or_like("field", String::from("foo"), LikeWildcard::After);
|
||||
///
|
||||
/// // Search for a value that has "foo" in it
|
||||
/// qb.or_like("field", String::from("foo"), LikeWildcard::Both);
|
||||
/// ```
|
||||
pub fn or_like(&mut self, field: &str, value: impl Any, position: LikeWildcard) -> &mut Self {
|
||||
self._like(field, value, position, "LIKE", "OR")
|
||||
}
|
||||
|
||||
/// Generates a `not like` clause
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = stringqb::query_builder::QueryBuilder::default();
|
||||
/// // Search for a value that does not end with "foo"
|
||||
/// qb.not_like("field", String::from("foo"), LikeWildcard::Before);
|
||||
///
|
||||
/// // Search for a value that does not start with "foo"
|
||||
/// qb.not_like("field", String::from("foo"), LikeWildcard::After);
|
||||
///
|
||||
/// // Search for a value that does not have "foo" in it
|
||||
/// qb.not_like("field", String::from("foo"), LikeWildcard::Both);
|
||||
/// ```
|
||||
pub fn not_like(&mut self, field: &str, value: impl Any, position: LikeWildcard) -> &mut Self {
|
||||
self._like(field, value, position, "NOT LIKE", "AND")
|
||||
}
|
||||
|
||||
/// Generates an OR NOT Like clause
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = stringqb::query_builder::QueryBuilder::default();
|
||||
/// // Search for a value that does not end with "foo"
|
||||
/// qb.or_not_like("field", String::from("foo"), LikeWildcard::Before);
|
||||
///
|
||||
/// // Search for a value that does not start with "foo"
|
||||
/// qb.or_not_like("field", String::from("foo"), LikeWildcard::After);
|
||||
///
|
||||
/// // Search for a value that does not have "foo" in it
|
||||
/// qb.or_not_like("field", String::from("foo"), LikeWildcard::Both);
|
||||
/// ```
|
||||
pub fn or_not_like(
|
||||
&mut self,
|
||||
field: &str,
|
||||
@ -264,6 +308,16 @@ impl QueryBuilder {
|
||||
}
|
||||
|
||||
/// Add a `having` clause to the query, prefixed with an `or`
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // By default, key = value
|
||||
/// qb.or_having("key", vec!["value"]);
|
||||
///
|
||||
/// // Other operators can be used with a separating space
|
||||
/// qb.or_having("clues <", vec![88]);
|
||||
/// ```
|
||||
pub fn or_having(&mut self, key: &str, value: Vec<impl Any>) -> &mut Self {
|
||||
self._having(key, value, "OR")
|
||||
}
|
||||
@ -294,16 +348,46 @@ impl QueryBuilder {
|
||||
|
||||
/// Alias method for `where`, as using the `where` method requires
|
||||
/// using the raw identifier `r#where`.
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // By default, key = value
|
||||
/// qb.wher("key", "value");
|
||||
///
|
||||
/// // Other operators can be used with a separating space
|
||||
/// qb.wher("key >", 4);
|
||||
/// ```
|
||||
pub fn wher(&mut self, key: &str, value: impl Any) -> &mut Self {
|
||||
self.r#where(key, value)
|
||||
self._where_string(key, value, "AND")
|
||||
}
|
||||
|
||||
/// Specify a condition for the `where` clause of the query, prefixed with `or`
|
||||
///
|
||||
/// By default does not have any query grouping.
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // By default, key = value
|
||||
/// qb.or_where("key", "value");
|
||||
///
|
||||
/// // Other operators can be used with a separating space
|
||||
/// qb.or_where("key !=", "foo");
|
||||
/// ```
|
||||
pub fn or_where(&mut self, key: &str, value: impl Any) -> &mut Self {
|
||||
self._where_string(key, value, "OR")
|
||||
}
|
||||
|
||||
/// Specify a `where in` clause for the query
|
||||
/// Specify a `where in` clause for the query. If called multiple times,
|
||||
/// will prefix the clause with `AND`
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // Look for a set of rows matching the values passed
|
||||
/// qb.where_in("key", vec![1,2,3]);
|
||||
/// ```
|
||||
pub fn where_in(&mut self, key: &str, values: Vec<impl Any>) -> &mut Self {
|
||||
self._where_in(key, values, "IN", "AND")
|
||||
}
|
||||
@ -489,7 +573,17 @@ impl QueryBuilder {
|
||||
// ! Query execution methods
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/// Execute the built query
|
||||
/// Execute the generated select query
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // The get() method actually calls the driver to run
|
||||
/// // the SQL query
|
||||
/// let query = db.select_vec(vec!["foo", "bar"])
|
||||
/// .from("table t")
|
||||
/// .get();
|
||||
/// ```
|
||||
pub fn get(&mut self) {
|
||||
let sql = self.get_compiled_select();
|
||||
|
||||
@ -502,6 +596,15 @@ impl QueryBuilder {
|
||||
}
|
||||
|
||||
/// Execute the generated insert query
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // The insert() method actually calls the driver to run
|
||||
/// // the SQL query
|
||||
/// let query = db.set("foo", 3)
|
||||
/// .insert("table");
|
||||
/// ```
|
||||
pub fn insert(&mut self, table: &str) {
|
||||
let sql = self.get_compiled_insert(table);
|
||||
|
||||
@ -509,6 +612,16 @@ impl QueryBuilder {
|
||||
}
|
||||
|
||||
/// Execute the generated update query
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // The update() method actually calls the driver to run
|
||||
/// // the SQL query
|
||||
/// let query = db.set("foo", 3)
|
||||
/// .wher("foo", 4)
|
||||
/// .update("table");
|
||||
/// ```
|
||||
pub fn update(&mut self, table: &str) {
|
||||
let sql = self.get_compiled_update(table);
|
||||
|
||||
@ -563,8 +676,18 @@ impl QueryBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Execute an SQL query
|
||||
pub fn query(&mut self, sql: &str) {
|
||||
/// Execute an SQL query with no parameters
|
||||
pub fn basic_query(&mut self, sql: &str) {
|
||||
self.driver.query(sql)
|
||||
}
|
||||
|
||||
/// Prepare an SQL query
|
||||
pub fn prepare(&mut self, sql: &str) -> Prepared {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/// Execute a prepared statement
|
||||
pub fn execute(&mut self, stmt: &Prepared, params: &[Box<dyn Any>]) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
@ -762,14 +885,15 @@ impl QueryBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
fn run(&mut self, _sql: &str) {
|
||||
fn run(&mut self, sql: &str) {
|
||||
let mut values: Vec<Box<Any>> = vec![];
|
||||
values.append(self.state.get_values());
|
||||
values.append(self.state.get_where_values());
|
||||
|
||||
// @TODO determine query result type
|
||||
// @TODO prepare/execute query, and return result
|
||||
unimplemented!();
|
||||
let stmt = self.prepare(sql);
|
||||
self.execute(&stmt, values)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user