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
|
/// Quote the identifiers passed, so the database does not
|
||||||
/// normalize the identifiers (eg, table, column, etc.)
|
/// normalize the identifiers (eg, table, column, etc.)
|
||||||
fn quote_identifier(&self, identifier: &str) -> String {
|
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,
|
// If the identifier is actually a comma-separated list,
|
||||||
// recurse to quote each identifier in the list
|
// recurse to quote each identifier in the list
|
||||||
@ -104,7 +104,7 @@ pub trait DatabaseDriver {
|
|||||||
// Runs a basic sql query on the database
|
// Runs a basic sql query on the database
|
||||||
// fn query(&self, sql: &str) -> Result<impl Any, impl Error>;
|
// 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<(), ()> {
|
fn prepare(&self, sql: &str) -> Result<(), ()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
//!
|
//!
|
||||||
//! Use of this driver requires enabling the `sqlite` feature.
|
//! 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 super::*;
|
||||||
|
|
||||||
use slite::NO_PARAMS;
|
use slite::NO_PARAMS;
|
||||||
@ -36,6 +37,18 @@ impl SQLiteDriver {
|
|||||||
|
|
||||||
self.connection = RefCell::new(Some(connection));
|
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 {
|
impl DatabaseDriver for SQLiteDriver {
|
||||||
|
11
src/lib.rs
11
src/lib.rs
@ -20,6 +20,10 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
|
||||||
|
#[cfg(feature = "sqlite")]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate slite;
|
||||||
|
|
||||||
pub mod drivers;
|
pub mod drivers;
|
||||||
pub mod fns;
|
pub mod fns;
|
||||||
pub mod query_builder;
|
pub mod query_builder;
|
||||||
@ -31,7 +35,12 @@ pub mod prelude {
|
|||||||
//! This includes enum types, traits,
|
//! This includes enum types, traits,
|
||||||
//! the Query Builder, and individual database drivers.
|
//! the Query Builder, and individual database drivers.
|
||||||
pub use crate::drivers::DatabaseDriver;
|
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")]
|
#[cfg(feature = "postgres")]
|
||||||
/// Postgres Driver
|
/// Postgres Driver
|
||||||
|
@ -86,6 +86,11 @@ pub struct QueryBuilder {
|
|||||||
driver: Box<dyn DatabaseDriver>,
|
driver: Box<dyn DatabaseDriver>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The struct representing a prepared statement
|
||||||
|
pub struct Prepared {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for QueryBuilder {
|
impl Default for QueryBuilder {
|
||||||
/// Creates a new QueryBuilder instance with default driver
|
/// Creates a new QueryBuilder instance with default driver
|
||||||
///
|
///
|
||||||
@ -179,7 +184,7 @@ impl QueryBuilder {
|
|||||||
self
|
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
|
/// than a result set
|
||||||
pub fn explain(&mut self) -> &mut Self {
|
pub fn explain(&mut self) -> &mut Self {
|
||||||
self.state.explain = true;
|
self.state.explain = true;
|
||||||
@ -225,16 +230,55 @@ impl QueryBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generates an `or like` clause
|
/// 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 {
|
pub fn or_like(&mut self, field: &str, value: impl Any, position: LikeWildcard) -> &mut Self {
|
||||||
self._like(field, value, position, "LIKE", "OR")
|
self._like(field, value, position, "LIKE", "OR")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a `not like` clause
|
/// 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 {
|
pub fn not_like(&mut self, field: &str, value: impl Any, position: LikeWildcard) -> &mut Self {
|
||||||
self._like(field, value, position, "NOT LIKE", "AND")
|
self._like(field, value, position, "NOT LIKE", "AND")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates an OR NOT Like clause
|
/// 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(
|
pub fn or_not_like(
|
||||||
&mut self,
|
&mut self,
|
||||||
field: &str,
|
field: &str,
|
||||||
@ -264,6 +308,16 @@ impl QueryBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add a `having` clause to the query, prefixed with an `or`
|
/// 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 {
|
pub fn or_having(&mut self, key: &str, value: Vec<impl Any>) -> &mut Self {
|
||||||
self._having(key, value, "OR")
|
self._having(key, value, "OR")
|
||||||
}
|
}
|
||||||
@ -294,16 +348,46 @@ impl QueryBuilder {
|
|||||||
|
|
||||||
/// Alias method for `where`, as using the `where` method requires
|
/// Alias method for `where`, as using the `where` method requires
|
||||||
/// using the raw identifier `r#where`.
|
/// 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 {
|
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`
|
/// 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 {
|
pub fn or_where(&mut self, key: &str, value: impl Any) -> &mut Self {
|
||||||
self._where_string(key, value, "OR")
|
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 {
|
pub fn where_in(&mut self, key: &str, values: Vec<impl Any>) -> &mut Self {
|
||||||
self._where_in(key, values, "IN", "AND")
|
self._where_in(key, values, "IN", "AND")
|
||||||
}
|
}
|
||||||
@ -489,7 +573,17 @@ impl QueryBuilder {
|
|||||||
// ! Query execution methods
|
// ! 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) {
|
pub fn get(&mut self) {
|
||||||
let sql = self.get_compiled_select();
|
let sql = self.get_compiled_select();
|
||||||
|
|
||||||
@ -502,6 +596,15 @@ impl QueryBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Execute the generated insert query
|
/// 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) {
|
pub fn insert(&mut self, table: &str) {
|
||||||
let sql = self.get_compiled_insert(table);
|
let sql = self.get_compiled_insert(table);
|
||||||
|
|
||||||
@ -509,6 +612,16 @@ impl QueryBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Execute the generated update query
|
/// 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) {
|
pub fn update(&mut self, table: &str) {
|
||||||
let sql = self.get_compiled_update(table);
|
let sql = self.get_compiled_update(table);
|
||||||
|
|
||||||
@ -563,8 +676,18 @@ impl QueryBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute an SQL query
|
/// Execute an SQL query with no parameters
|
||||||
pub fn query(&mut self, sql: &str) {
|
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!();
|
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![];
|
let mut values: Vec<Box<Any>> = vec![];
|
||||||
values.append(self.state.get_values());
|
values.append(self.state.get_values());
|
||||||
values.append(self.state.get_where_values());
|
values.append(self.state.get_where_values());
|
||||||
|
|
||||||
// @TODO determine query result type
|
// @TODO determine query result type
|
||||||
// @TODO prepare/execute query, and return result
|
// @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