Misc bugfixes, doc updates
This commit is contained in:
parent
aad53f0f20
commit
eb838306ec
@ -102,7 +102,9 @@ pub trait DatabaseDriver {
|
||||
}
|
||||
|
||||
// Runs a basic sql query on the database
|
||||
// fn query(&self, sql: &str) -> Result<impl Any, impl Error>;
|
||||
fn query(&self, sql: &str) -> Result<Box<dyn Any>, Box<dyn Any>> {
|
||||
Ok(Box::new(String::from(sql)))
|
||||
}
|
||||
|
||||
/// Prepares an sql statement for the database
|
||||
fn prepare(&self, sql: &str) -> Result<(), ()> {
|
||||
|
@ -33,18 +33,6 @@ impl PostgresDriver {
|
||||
|
||||
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, &[])
|
||||
}
|
||||
}
|
||||
|
||||
impl DatabaseDriver for PostgresDriver {
|
||||
@ -55,4 +43,22 @@ impl DatabaseDriver for PostgresDriver {
|
||||
fn random(&self) -> String {
|
||||
String::from(" RANDOM()")
|
||||
}
|
||||
|
||||
fn query(&self, sql: &str) -> Result<Box<dyn Any>, Box<dyn Any>> {
|
||||
if self.connection.borrow().is_none() {
|
||||
panic!("No database connection.");
|
||||
}
|
||||
|
||||
let result = self
|
||||
.connection
|
||||
.borrow_mut()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.query(sql, &[]);
|
||||
|
||||
match result {
|
||||
Ok(res) => Ok(Box::new(res)),
|
||||
Err(e) => Err(Box::new(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,12 +35,7 @@ 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
|
||||
|
@ -79,7 +79,36 @@ enum QueryType {
|
||||
Delete,
|
||||
}
|
||||
|
||||
/// The struct representing a query builder
|
||||
/// QueryBuilder for general SQL queries
|
||||
///
|
||||
/// ```
|
||||
/// use stringqb::prelude::*;
|
||||
///
|
||||
/// // You probably do not want to use the default driver, as it
|
||||
/// // is basically a mock for testing
|
||||
/// use stringqb::drivers::DefaultDriver;
|
||||
///
|
||||
/// // The query builder must be mutable to be useful
|
||||
/// let mut qb = QueryBuilder::new(DefaultDriver::new());
|
||||
///
|
||||
/// // Each builder method returns a mutable reference to itself so
|
||||
/// // the methods are chainable
|
||||
/// qb.select("field as f")
|
||||
/// .from("table t")
|
||||
/// .inner_join("table_two tt", "field2 as ff", "=", "f")
|
||||
/// .wher("f >", 3);
|
||||
///
|
||||
/// // Since they are references, you do not have to chain.
|
||||
/// let sql = qb.get_compiled_select();
|
||||
///
|
||||
/// # assert_eq!(
|
||||
/// # sql,
|
||||
/// # r#"SELECT "field" AS "f"
|
||||
/// FROM "table" "t"
|
||||
/// INNER JOIN "table_two" "tt" ON "field2" AS "ff"=f
|
||||
/// WHERE "f" > ?"#
|
||||
/// # );
|
||||
/// ```
|
||||
pub struct QueryBuilder {
|
||||
/// The struct to store the query builder info
|
||||
state: QueryState,
|
||||
@ -87,9 +116,7 @@ pub struct QueryBuilder {
|
||||
}
|
||||
|
||||
/// The struct representing a prepared statement
|
||||
pub struct Prepared {
|
||||
|
||||
}
|
||||
pub struct Prepared {}
|
||||
|
||||
impl Default for QueryBuilder {
|
||||
/// Creates a new QueryBuilder instance with default driver
|
||||
@ -109,19 +136,19 @@ impl QueryBuilder {
|
||||
/// ```no_run
|
||||
/// use stringqb::prelude::*;
|
||||
///
|
||||
/// // You probably do not want to use the default driver, as it
|
||||
/// // is basically a mock for testing
|
||||
/// use stringqb::drivers::DefaultDriver;
|
||||
/// // Postgres Driver (If enabled)
|
||||
/// let pgDriver = PostgresDriver::new("postgres://");
|
||||
///
|
||||
/// // The query builder must be mutable to be useful
|
||||
/// let mut qb = QueryBuilder::new(DefaultDriver::new());
|
||||
/// #[cfg(feature = "sqlite")]
|
||||
/// // SQLite Driver (memory)
|
||||
/// let liteMemoryDriver = SQLiteDriver::new(":memory:");
|
||||
///
|
||||
/// // Each builder method returns a mutable reference to itself so
|
||||
/// // the methods are chainable
|
||||
/// qb.select("field f").from("table");
|
||||
/// #[cfg(feature = "sqlite")]
|
||||
/// // SQLite Driver (file)
|
||||
/// let liteDriver = SQLiteDriver::new("/path/to/db.sqlite3");
|
||||
///
|
||||
/// // Since they are references, you do not have to chain.
|
||||
/// let sql = qb.get_compiled_select();
|
||||
/// // The variable to the query builder must be mutable
|
||||
/// let mut queryBuilder = QueryBuilder::new(pgDriver);
|
||||
/// ```
|
||||
pub fn new(driver: impl DatabaseDriver + 'static) -> Self {
|
||||
QueryBuilder {
|
||||
@ -137,28 +164,13 @@ impl QueryBuilder {
|
||||
/// Set the fields to select from the database as a string
|
||||
///
|
||||
/// ```no_run
|
||||
/// # let mut qb = stringqb::query_builder::QueryBuilder::default();
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // You can also alias field names
|
||||
/// qb.select("foo as bar");
|
||||
/// ```
|
||||
pub fn select(&mut self, fields: &str) -> &mut Self {
|
||||
lazy_static! {
|
||||
static ref RE: Regex = Regex::new(r"(?i) as ").unwrap();
|
||||
};
|
||||
|
||||
let fields = split_map_join(fields, ",", |s| {
|
||||
if !RE.is_match(s) {
|
||||
return self.driver.quote_identifier(s.trim());
|
||||
}
|
||||
|
||||
// Do a operation similar to split_map_join for the
|
||||
// regex matches, quoting each identifier
|
||||
RE.split(s)
|
||||
.into_iter()
|
||||
.map(|p| self.driver.quote_identifier(p))
|
||||
.collect::<Vec<String>>()
|
||||
.join(" as ")
|
||||
});
|
||||
let fields = self.quote_fields(fields);
|
||||
|
||||
self.state.append_select_string(&fields);
|
||||
|
||||
@ -168,7 +180,8 @@ impl QueryBuilder {
|
||||
/// Set the fields to select from the database as a Vector
|
||||
///
|
||||
/// ```no_run
|
||||
/// # let mut qb = stringqb::query_builder::QueryBuilder::default();
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // You can also alias via a vector of fields
|
||||
/// qb.select_vec(vec!["foo as bar", "baz"]);
|
||||
/// ```
|
||||
@ -195,8 +208,9 @@ impl QueryBuilder {
|
||||
/// Specify the database table to select from
|
||||
///
|
||||
/// ```no_run
|
||||
/// # let mut qb = stringqb::query_builder::QueryBuilder::default();
|
||||
/// // You can specifiy an alias for the table
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // You can specify an alias for the table
|
||||
/// qb.from("products p");
|
||||
/// ```
|
||||
pub fn from(&mut self, table_name: &str) -> &mut Self {
|
||||
@ -215,7 +229,7 @@ impl QueryBuilder {
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = stringqb::query_builder::QueryBuilder::default();
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // Search for a value that ends with "foo"
|
||||
/// qb.like("field", String::from("foo"), LikeWildcard::Before);
|
||||
///
|
||||
@ -233,7 +247,7 @@ impl QueryBuilder {
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = stringqb::query_builder::QueryBuilder::default();
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // Search for a value that ends with "foo"
|
||||
/// qb.or_like("field", String::from("foo"), LikeWildcard::Before);
|
||||
///
|
||||
@ -251,7 +265,7 @@ impl QueryBuilder {
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = stringqb::query_builder::QueryBuilder::default();
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // Search for a value that does not end with "foo"
|
||||
/// qb.not_like("field", String::from("foo"), LikeWildcard::Before);
|
||||
///
|
||||
@ -269,7 +283,7 @@ impl QueryBuilder {
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = stringqb::query_builder::QueryBuilder::default();
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // Search for a value that does not end with "foo"
|
||||
/// qb.or_not_like("field", String::from("foo"), LikeWildcard::Before);
|
||||
///
|
||||
@ -393,16 +407,37 @@ impl QueryBuilder {
|
||||
}
|
||||
|
||||
/// Specify a `where in` clause for the query, prefixed with `or`
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // Look for a set of rows matching the values passed
|
||||
/// qb.or_where_in("key", vec![1,2,3]);
|
||||
/// ```
|
||||
pub fn or_where_in(&mut self, key: &str, values: Vec<impl Any>) -> &mut Self {
|
||||
self._where_in(key, values, "IN", "OR")
|
||||
}
|
||||
|
||||
/// Specify a `where not in` clause for the query
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // Look for a set of rows not matching the values passed
|
||||
/// qb.where_not_in("key", vec![1,2,3]);
|
||||
/// ```
|
||||
pub fn where_not_in(&mut self, key: &str, values: Vec<impl Any>) -> &mut Self {
|
||||
self._where_in(key, values, "NOT IN", "AND")
|
||||
}
|
||||
|
||||
/// Specify a `where not in` clause for the query, prefixed with `or`
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // Look for a set of rows not matching the values passed
|
||||
/// qb.or_where_not_in("key", vec![1,2,3]);
|
||||
/// ```
|
||||
pub fn or_where_not_in(&mut self, key: &str, values: Vec<impl Any>) -> &mut Self {
|
||||
self._where_in(key, values, "NOT IN", "OR")
|
||||
}
|
||||
@ -412,6 +447,15 @@ impl QueryBuilder {
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/// Set a key and value for an insert or update query
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // Can be called multiple times to set multiple values
|
||||
/// qb.set("foo", 3)
|
||||
/// .set("bar", 4)
|
||||
/// .insert("table");
|
||||
/// ```
|
||||
pub fn set(&mut self, key: &str, value: impl Any) -> &mut Self {
|
||||
let key = self.driver.quote_identifier(key);
|
||||
self.state
|
||||
@ -431,11 +475,25 @@ impl QueryBuilder {
|
||||
}
|
||||
|
||||
/// Convenience method for a `left` join
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // Note that the value is not prepared/escaped, due to it often being a column
|
||||
/// qb.left_join("table1", "column1", "<>", "foo");
|
||||
/// ```
|
||||
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
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // Note that the value is not prepared/escaped, due to it often being a column
|
||||
/// qb.inner_join("table1", "column1", "<>", "foo");
|
||||
/// ```
|
||||
pub fn inner_join(&mut self, table: &str, col: &str, op: &str, value: &str) -> &mut Self {
|
||||
self.join(table, col, op, value, JoinType::Inner)
|
||||
}
|
||||
@ -445,7 +503,7 @@ impl QueryBuilder {
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // Note that the value is not escaped, due to it often being a column
|
||||
/// // Note that the value is not prepared/escaped, due to it often being a column
|
||||
/// qb.join("table1", "column1", "<>", "foo", JoinType::Inner);
|
||||
/// ```
|
||||
pub fn join(
|
||||
@ -456,9 +514,16 @@ impl QueryBuilder {
|
||||
value: &str,
|
||||
join_type: JoinType,
|
||||
) -> &mut Self {
|
||||
let table = self.driver.quote_identifier(table);
|
||||
let col = self.driver.quote_identifier(col);
|
||||
let condition = table + " ON " + &col + op + value;
|
||||
let col = self.quote_fields(col);
|
||||
let table = self.quote_table(table);
|
||||
|
||||
let condition = format!(
|
||||
"{} ON {}{}{}",
|
||||
table,
|
||||
&col,
|
||||
op,
|
||||
value
|
||||
);
|
||||
|
||||
let join_type = match join_type {
|
||||
JoinType::Cross => "CROSS ",
|
||||
@ -520,6 +585,11 @@ impl QueryBuilder {
|
||||
|
||||
/// Add an offset to the query
|
||||
pub fn offset(&mut self, offset: usize) -> &mut Self {
|
||||
assert!(
|
||||
self.state.offset.is_some(),
|
||||
"You must set a limit to set an offset"
|
||||
);
|
||||
|
||||
self.state.offset = Some(offset);
|
||||
|
||||
self
|
||||
@ -531,16 +601,28 @@ impl QueryBuilder {
|
||||
|
||||
/// Start a logical grouping in the current query
|
||||
pub fn group_start(&mut self) -> &mut Self {
|
||||
let conj = if ! self.state.has_where_clause() {
|
||||
"\nWHERE "
|
||||
} else {
|
||||
" "
|
||||
};
|
||||
|
||||
self.state
|
||||
.append_query_map(QueryClauseType::GroupStart, " ", "(");
|
||||
.append_query_map(QueryClauseType::GroupStart, conj, "(");
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Start a logical grouping, prefixed with `not`
|
||||
pub fn not_group_start(&mut self) -> &mut Self {
|
||||
let conj = if ! self.state.has_where_clause() {
|
||||
"\nWHERE "
|
||||
} else {
|
||||
" AND "
|
||||
};
|
||||
|
||||
self.state
|
||||
.append_query_map(QueryClauseType::GroupStart, " AND ", "NOT (");
|
||||
.append_query_map(QueryClauseType::GroupStart, conj, "NOT (");
|
||||
|
||||
self
|
||||
}
|
||||
@ -580,7 +662,7 @@ impl QueryBuilder {
|
||||
/// # 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"])
|
||||
/// let query = qb.select_vec(vec!["foo", "bar"])
|
||||
/// .from("table t")
|
||||
/// .get();
|
||||
/// ```
|
||||
@ -602,7 +684,7 @@ impl QueryBuilder {
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // The insert() method actually calls the driver to run
|
||||
/// // the SQL query
|
||||
/// let query = db.set("foo", 3)
|
||||
/// let query = qb.set("foo", 3)
|
||||
/// .insert("table");
|
||||
/// ```
|
||||
pub fn insert(&mut self, table: &str) {
|
||||
@ -618,7 +700,7 @@ impl QueryBuilder {
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // The update() method actually calls the driver to run
|
||||
/// // the SQL query
|
||||
/// let query = db.set("foo", 3)
|
||||
/// let query = qb.set("foo", 3)
|
||||
/// .wher("foo", 4)
|
||||
/// .update("table");
|
||||
/// ```
|
||||
@ -629,6 +711,15 @@ impl QueryBuilder {
|
||||
}
|
||||
|
||||
/// Execute the generated delete query
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use stringqb::prelude::*;
|
||||
/// # let mut qb = QueryBuilder::default();
|
||||
/// // The delete() method actually calls the driver to run
|
||||
/// // the SQL query
|
||||
/// let query = qb.wher("foo", 3)
|
||||
/// .delete("table");
|
||||
/// ```
|
||||
pub fn delete(&mut self, table: &str) {
|
||||
let sql = self.get_compiled_delete(table);
|
||||
|
||||
@ -670,14 +761,14 @@ impl QueryBuilder {
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/// Get a new instance of the query builder
|
||||
pub fn reset(&mut self) -> &Self {
|
||||
pub fn reset(&mut self) -> &mut Self {
|
||||
self.state = QueryState::new();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Execute an SQL query with no parameters
|
||||
pub fn basic_query(&mut self, sql: &str) {
|
||||
pub fn basic_query(&mut self, sql: &str) -> Result<Box<dyn Any>, Box<dyn Any>> {
|
||||
self.driver.query(sql)
|
||||
}
|
||||
|
||||
@ -691,6 +782,32 @@ impl QueryBuilder {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/// Quotes table column(s)/field(s) accounting for 'as' aliases
|
||||
fn quote_fields(&mut self, fields: &str) -> String {
|
||||
lazy_static! {
|
||||
static ref RE: Regex = Regex::new(r"(?i) as ").unwrap();
|
||||
};
|
||||
|
||||
split_map_join(fields, ",", |s| {
|
||||
if !RE.is_match(s) {
|
||||
return self.driver.quote_identifier(s.trim());
|
||||
}
|
||||
|
||||
// Do a operation similar to split_map_join for the
|
||||
// regex matches, quoting each identifier
|
||||
RE.split(s)
|
||||
.into_iter()
|
||||
.map(|p| self.driver.quote_identifier(p))
|
||||
.collect::<Vec<String>>()
|
||||
.join(" AS ")
|
||||
})
|
||||
}
|
||||
|
||||
/// Quotes table(s), accounting for aliases
|
||||
pub fn quote_table(&mut self, table: &str) -> String {
|
||||
split_map_join(table, " ", |s| self.driver.quote_identifier(s))
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ! Implementation Details
|
||||
// --------------------------------------------------------------------------
|
||||
@ -703,6 +820,12 @@ impl QueryBuilder {
|
||||
like: &str,
|
||||
conj: &str,
|
||||
) -> &mut Self {
|
||||
let conj = if ! self.state.has_where_clause() {
|
||||
"\nWHERE "
|
||||
} else {
|
||||
conj
|
||||
};
|
||||
|
||||
let field = self.driver.quote_identifier(field);
|
||||
|
||||
let like = format!("{} {} ?", field, like);
|
||||
@ -775,6 +898,12 @@ impl QueryBuilder {
|
||||
|
||||
let str = format!("{} {} ({}) ", key, in_str, placeholders.join(","));
|
||||
|
||||
let conj = if ! self.state.has_where_clause() {
|
||||
"\nWHERE "
|
||||
} else {
|
||||
conj
|
||||
};
|
||||
|
||||
self.state
|
||||
.append_query_map(QueryClauseType::WhereIn, conj, &str);
|
||||
|
||||
@ -805,21 +934,29 @@ impl QueryBuilder {
|
||||
|
||||
item += &item2;
|
||||
|
||||
let conj = if self.state.query_map.len() == 0 || ( ! self.state.has_where_clause()) {
|
||||
String::from("\nWHERE")
|
||||
} else {
|
||||
String::from(conj)
|
||||
};
|
||||
|
||||
let conj = if last_item.is_some() {
|
||||
let last_item = last_item.unwrap();
|
||||
|
||||
match last_item.clause_type {
|
||||
QueryClauseType::GroupStart => String::from(""),
|
||||
_ => format!(" {} ", conj),
|
||||
_ => format!("{} ", conj),
|
||||
}
|
||||
} else {
|
||||
format!(" {} ", conj)
|
||||
format!("{} ", conj)
|
||||
};
|
||||
|
||||
self.state
|
||||
.append_query_map(QueryClauseType::Where, &conj, &item);
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn compile(&self, query_type: QueryType, table: &str) -> String {
|
||||
// Get the base clause for the query
|
||||
let base_sql = self.compile_type(query_type, &self.driver.quote_identifier(table));
|
||||
@ -893,7 +1030,7 @@ impl QueryBuilder {
|
||||
// @TODO determine query result type
|
||||
// @TODO prepare/execute query, and return result
|
||||
let stmt = self.prepare(sql);
|
||||
self.execute(&stmt, values)
|
||||
self.execute(&stmt, &values)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1041,12 +1178,6 @@ impl QueryState {
|
||||
}
|
||||
|
||||
fn append_query_map(&mut self, clause_type: QueryClauseType, conj: &str, s: &str) -> &mut Self {
|
||||
let conj = if self.query_map.len() == 0 {
|
||||
" WHERE "
|
||||
} else {
|
||||
conj
|
||||
};
|
||||
|
||||
self.query_map.push(QueryClause::new(clause_type, conj, s));
|
||||
|
||||
self
|
||||
@ -1110,6 +1241,20 @@ impl QueryState {
|
||||
&mut self.where_values
|
||||
}
|
||||
|
||||
fn has_where_clause(&self) -> bool {
|
||||
let has_clause = false;
|
||||
|
||||
for clause in self.query_map.iter() {
|
||||
match clause.clause_type {
|
||||
QueryClauseType::Where => return true,
|
||||
QueryClauseType::WhereIn => return true,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
has_clause
|
||||
}
|
||||
|
||||
fn set_from_string(&mut self, s: &str) -> &mut Self {
|
||||
self.from_string = String::from(s);
|
||||
|
||||
@ -1172,7 +1317,7 @@ mod tests {
|
||||
qb.from("test").where_in("foo", vec![0, 1, 2, 3, 4, 5]);
|
||||
|
||||
let sql = qb.get_compiled_select();
|
||||
let expected = "SELECT *\nFROM \"test\" WHERE \"foo\" IN (?,?,?,?,?,?) ";
|
||||
let expected = "SELECT *\nFROM \"test\"\nWHERE \"foo\" IN (?,?,?,?,?,?) ";
|
||||
|
||||
assert_eq!(sql, expected);
|
||||
}
|
||||
|
@ -86,8 +86,8 @@ pub enum ToDriverOutput<'a> {
|
||||
// Generically allow any type that can be converted into a ValueRef
|
||||
// to be converted into a ToSqlOutput as well.
|
||||
impl<'a, T: ?Sized> From<&'a T> for ToDriverOutput<'a>
|
||||
where
|
||||
&'a T: Into<ValueRef<'a>>,
|
||||
where
|
||||
&'a T: Into<ValueRef<'a>>,
|
||||
{
|
||||
fn from(t: &'a T) -> Self {
|
||||
ToDriverOutput::Borrowed(t.into())
|
||||
@ -120,16 +120,13 @@ impl<'a, T: ?Sized> From<&'a T> for ToDriverOutput<'a>
|
||||
//from_value!(f64);
|
||||
//from_value!(Vec<u8>);
|
||||
|
||||
|
||||
/// Types that can be converted to a type that the driver understands
|
||||
pub trait ToDriver {
|
||||
fn to_driver(&self) -> Result<ToDriverOutput<'_>, ()>;
|
||||
}
|
||||
|
||||
/// A trait for types that can be created from the result of a query on the driver
|
||||
pub trait FromDriver: Sized {
|
||||
|
||||
}
|
||||
pub trait FromDriver: Sized {}
|
||||
|
||||
/// Enum struct for mapping between database and Rust types
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
|
||||
|
@ -15,7 +15,7 @@ fn select_keys_as_query() {
|
||||
|
||||
let sql = qb.select("foo as bar, baz").from("a").get_compiled_select();
|
||||
|
||||
assert_eq!(sql, "SELECT \"foo\" as \"bar\",\"baz\"\nFROM \"a\"");
|
||||
assert_eq!(sql, "SELECT \"foo\" AS \"bar\",\"baz\"\nFROM \"a\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -54,7 +54,7 @@ fn select_where() {
|
||||
qb.from("test").r#where("foo", "bar");
|
||||
|
||||
let sql = qb.get_compiled_select();
|
||||
let expected = "SELECT *\nFROM \"test\" WHERE \"foo\"=?";
|
||||
let expected = "SELECT *\nFROM \"test\"\nWHERE \"foo\"=?";
|
||||
|
||||
assert_eq!(sql, expected);
|
||||
}
|
||||
@ -66,7 +66,7 @@ fn select_where_in() {
|
||||
qb.from("test").where_in("foo", vec![0, 1, 2, 3, 4, 5]);
|
||||
|
||||
let sql = qb.get_compiled_select();
|
||||
let expected = "SELECT *\nFROM \"test\" WHERE \"foo\" IN (?,?,?,?,?,?) ";
|
||||
let expected = "SELECT *\nFROM \"test\"\nWHERE \"foo\" IN (?,?,?,?,?,?) ";
|
||||
|
||||
assert_eq!(sql, expected);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user