More implementation

This commit is contained in:
Timothy Warren 2019-04-12 17:09:59 -04:00
parent 4cc6f079c3
commit f7efadeb66
10 changed files with 148 additions and 30 deletions

View File

@ -28,14 +28,9 @@ version="15.1.0"
optional=true
package="mysql"
[dependencies.ms]
version="0.3.2"
optional=true
package="tiberius"
[features]
default=['postgres']
postgres=['pg']
sqlite=['slite']
mysql=['my']
mssql=['ms']
mssql=[]

View File

@ -37,7 +37,15 @@ impl DefaultDriver {
}
}
impl DatabaseDriver for DefaultDriver {}
impl DatabaseDriver for DefaultDriver {
fn explain(&self, sql: &str) -> String {
return format!("EXPLAIN {}", sql)
}
fn random(&self) -> String {
String::from(" RANDOM")
}
}
/// Database Driver Trait
///
@ -96,6 +104,32 @@ pub trait DatabaseDriver: fmt::Debug {
// Runs a basic sql query on the database
// fn query(&self, query: &str) -> Result<(), ()>;
// ------------------------------------------------------------------------
// ! Driver-specific SQL methods
// ------------------------------------------------------------------------
/// Take an existing sql query and add a limit and/or offset
fn limit(&self, sql: &str, limit: Option<usize>, offset: Option<usize>) -> String {
let mut sql = sql.to_string();
if limit.is_some() {
sql += &format!("\nLIMIT {}", limit.unwrap());
}
if offset.is_some() {
sql += &format!(" OFFSET {}", offset.unwrap());
}
sql
}
/// Get the query plan for the existing sql
fn explain(&self, sql: &str) -> String;
/// Get the database's keyword for sorting randomly
fn random(&self) -> String;
}
#[cfg(test)]

View File

@ -1,5 +1,8 @@
//! Database Driver for MSSQL
//!
//! Note:
//! **This driver will probably never be fully implemented**
//!
//! Contains database-specific query data
use super::*;
@ -20,6 +23,14 @@ impl DatabaseDriver for MSSQL {
fn _quotes(&self) -> (char, char) {
('[', ']')
}
fn explain(&self, sql: &str) -> String {
sql.to_string()
}
fn random(&self) -> String {
String::from(" RANDOM")
}
}
#[cfg(test)]

View File

@ -5,21 +5,43 @@ use super::*;
/// The struct implementing the `DatabaseDriver` trait
#[derive(Debug)]
pub struct MySQL;
pub struct MySQLDriver;
impl MySQL {
/// Create a MySQL driver
impl MySQLDriver {
/// Create a MySQLDriver driver
pub fn new() -> Self {
MySQL {}
MySQLDriver {}
}
}
impl DatabaseDriver for MySQL {
impl DatabaseDriver for MySQLDriver {
/// Get which characters are used to delimit identifiers
/// such as tables, and columns
fn _quotes(&self) -> (char, char) {
('`', '`')
}
fn limit(&self, sql: &str, limit: Option<usize>, offset: Option<usize>) -> String {
if limit.is_none() {
return sql.to_string();
}
// Limit and Offset are defined
if offset.is_some() {
return format!("{} LIMIT {}.{}", sql, offset.unwrap(), limit.unwrap());
}
// Limit is defined
format!("{} LIMIT {}", sql, limit.unwrap())
}
fn explain(&self, sql: &str) -> String {
return format!("EXPLAIN EXTENDED {}", sql)
}
fn random(&self) -> String {
String::from(" RAND() DESC")
}
}
#[cfg(test)]
@ -28,7 +50,7 @@ mod tests {
#[test]
fn test_quote_identifier_backtick_quote() {
let driver = MySQL::new();
let driver = MySQLDriver::new();
assert_eq!(
driver.quote_identifier("foo, bar, baz"),
@ -42,7 +64,7 @@ mod tests {
#[test]
fn test_quote_identifiers_backtick_quote() {
let driver = MySQL::new();
let driver = MySQLDriver::new();
assert_eq!(
driver.quote_identifiers(vec![

View File

@ -5,13 +5,21 @@ use super::*;
/// The struct implementing the `DatabaseDriver` trait
#[derive(Debug)]
pub struct Postgres;
pub struct PostgresDriver;
impl Postgres {
/// Create a Postgres driver
impl PostgresDriver {
/// Create a PostgresDriver driver
pub fn new() -> Self {
Postgres {}
PostgresDriver {}
}
}
impl DatabaseDriver for Postgres {}
impl DatabaseDriver for PostgresDriver {
fn explain(&self, sql: &str) -> String {
return format!("EXPLAIN VERBOSE {}", sql)
}
fn random(&self) -> String {
String::from(" RANDOM()")
}
}

View File

@ -5,13 +5,22 @@ use super::*;
/// The struct implementing the `DatabaseDriver` trait
#[derive(Debug)]
pub struct SQLite;
pub struct SQLiteDriver;
impl SQLite {
/// Create an SQLite driver
impl SQLiteDriver {
/// Create an SQLiteDriver driver
pub fn new() -> Self {
SQLite {}
SQLiteDriver {}
}
}
impl DatabaseDriver for SQLiteDriver {
fn explain(&self, sql: &str) -> String {
return format!("EXPLAIN QUERY PLAN {}", sql)
}
fn random(&self) -> String {
String::from(" RANDOM()")
}
}
impl DatabaseDriver for SQLite {}

View File

@ -17,7 +17,21 @@ pub mod query_builder;
pub mod prelude {
//! Re-exports important traits and types.
//!
//! This includes enum types, traits,
//! the Query Builder, and individual database drivers.
pub use crate::enums::*;
pub use crate::drivers::{DatabaseDriver, DefaultDriver};
pub use crate::drivers::DatabaseDriver;
pub use crate::query_builder::QueryBuilder;
#[cfg(feature = "postgres")]
pub use crate::drivers::postgres::PostgresDriver;
#[cfg(feature = "sqlite")]
pub use crate::drivers::sqlite::SQLiteDriver;
#[cfg(feature = "mysql")]
pub use crate::drivers::mysql::MySQLDriver;
// MSSQL is missing on purpose, as it is not a real priority to actually implement
}

View File

@ -1,10 +1,8 @@
//! This main file is just for temparary testing
use stringqb::drivers::postgres::Postgres;
use stringqb::query_builder::QueryBuilder;
// use stringqb::types::{SQLType, Type};
use stringqb::prelude::*;
fn main() {
let mut qb = QueryBuilder::new(Postgres::new());
let mut qb = QueryBuilder::new(PostgresDriver::new());
qb.set("foo", Box::new("bar"))
.set("bar", Box::new(12))

View File

@ -53,6 +53,13 @@ impl QueryBuilder {
///
/// // 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 f").from("table");
///
/// // Since they are references, you do not have to chain.
/// let sql = qb.get_compiled_select();
/// ```
pub fn new(driver: impl DatabaseDriver + 'static) -> Self {
QueryBuilder {

View File

@ -1,4 +1,4 @@
use stringqb::query_builder::QueryBuilder;
use stringqb::prelude::*;
#[test]
fn minimal_select_query() {
@ -47,6 +47,26 @@ fn select_without_from() {
qb.get_compiled_select();
}
#[test]
fn select_where_in() {
let mut qb = QueryBuilder::default();
qb.from("test")
.where_in("foo", vec![
Box::new(0),
Box::new(1),
Box::new(2),
Box::new(3),
Box::new(4),
Box::new(5)
]);
let sql = qb.get_compiled_select();
let expected = "SELECT *\nFROM \"test\" WHERE \"foo\" IN (?,?,?,?,?,?) ";
assert_eq!(sql, expected);
}
#[test]
fn basic_insert_query() {
let mut qb = QueryBuilder::default();