2019-04-09 18:55:53 -04:00
|
|
|
//! Database Drivers
|
2019-04-05 20:46:07 -04:00
|
|
|
//!
|
|
|
|
//! Drivers represent a connection to a specific type of database engine
|
2019-04-09 17:33:26 -04:00
|
|
|
use crate::split_map_join;
|
2019-04-05 20:46:07 -04:00
|
|
|
use std::fmt;
|
|
|
|
|
|
|
|
#[cfg(feature = "postgres")]
|
2019-04-09 14:13:37 -04:00
|
|
|
pub mod postgres;
|
2019-04-05 20:46:07 -04:00
|
|
|
|
|
|
|
#[cfg(feature = "sqlite")]
|
2019-04-09 14:13:37 -04:00
|
|
|
pub mod sqlite;
|
2019-04-05 20:46:07 -04:00
|
|
|
|
|
|
|
#[cfg(feature = "mysql")]
|
2019-04-09 14:13:37 -04:00
|
|
|
pub mod mysql;
|
2019-04-05 20:46:07 -04:00
|
|
|
|
|
|
|
#[cfg(feature = "mssql")]
|
2019-04-09 14:13:37 -04:00
|
|
|
pub mod mssql;
|
2019-04-05 20:46:07 -04:00
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct Connection;
|
|
|
|
|
|
|
|
/// Result for a db query
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct QueryResult;
|
|
|
|
|
2019-04-09 14:13:37 -04:00
|
|
|
/// Empty Driver implementation
|
|
|
|
///
|
|
|
|
/// Good for general testing
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct DefaultDriver;
|
|
|
|
|
|
|
|
impl DefaultDriver {
|
2019-04-10 14:03:28 -04:00
|
|
|
/// Create a `DefaultDriver`
|
2019-04-09 14:13:37 -04:00
|
|
|
pub fn new() -> Self {
|
|
|
|
DefaultDriver {}
|
|
|
|
}
|
2019-04-05 20:46:07 -04:00
|
|
|
}
|
|
|
|
|
2019-04-09 14:13:37 -04:00
|
|
|
impl DatabaseDriver for DefaultDriver {}
|
|
|
|
|
2019-04-05 20:46:07 -04:00
|
|
|
/// Database Driver Trait
|
|
|
|
///
|
|
|
|
/// Interface between the database connection library and the query builder
|
|
|
|
pub trait DatabaseDriver: fmt::Debug {
|
|
|
|
/// Get which characters are used to delimit identifiers
|
|
|
|
/// such as tables, and columns
|
|
|
|
fn _quotes(&self) -> (char, char) {
|
|
|
|
('"', '"')
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Vector version of `quote_identifier`
|
2019-04-11 11:44:06 -04:00
|
|
|
fn quote_identifiers(&self, identifiers: Vec<String>) -> Vec<String> {
|
2019-04-05 20:46:07 -04:00
|
|
|
let mut output: Vec<String> = vec![];
|
|
|
|
|
|
|
|
for identifier in identifiers {
|
2019-04-11 11:44:06 -04:00
|
|
|
output.push(self.quote_identifier(&identifier).to_string());
|
2019-04-05 20:46:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
output
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Quote the identifiers passed, so the database does not
|
|
|
|
/// normalize the identifiers (eg, table, column, etc.)
|
|
|
|
fn quote_identifier(&self, identifier: &str) -> String {
|
2019-04-10 14:03:28 -04:00
|
|
|
let identifier = &mut String::from(identifier);
|
2019-04-05 20:46:07 -04:00
|
|
|
|
2019-04-05 22:37:06 -04:00
|
|
|
// If the identifier is actually a comma-separated list,
|
2019-04-05 20:46:07 -04:00
|
|
|
// recurse to quote each identifier in the list
|
|
|
|
if identifier.contains(",") {
|
|
|
|
// This was the only way I could figure to get
|
|
|
|
// around mutable string reference scope hell
|
2019-04-09 18:55:53 -04:00
|
|
|
identifier.replace_range(
|
|
|
|
..,
|
|
|
|
&split_map_join(identifier, ",", |part| self.quote_identifier(part.trim())),
|
|
|
|
);
|
2019-04-05 20:46:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
let (open_char, close_char) = self._quotes();
|
|
|
|
|
2019-04-09 17:33:26 -04:00
|
|
|
let trimmed_tiers = split_map_join(identifier, ".", |tier| {
|
2019-04-09 17:14:07 -04:00
|
|
|
let tier = tier.trim();
|
2019-04-05 22:37:06 -04:00
|
|
|
if tier.starts_with(open_char) && tier.ends_with(close_char) {
|
2019-04-09 17:14:07 -04:00
|
|
|
return tier.to_string();
|
2019-04-05 20:46:07 -04:00
|
|
|
}
|
2019-04-09 17:14:07 -04:00
|
|
|
|
2019-04-10 14:03:28 -04:00
|
|
|
// Here where the quoting actually happens. Everything
|
|
|
|
// else is breaking down the identifier list for this.
|
2019-04-09 17:14:07 -04:00
|
|
|
format!("{}{}{}", &open_char, tier, &close_char)
|
|
|
|
});
|
|
|
|
|
|
|
|
trimmed_tiers
|
2019-04-05 22:37:06 -04:00
|
|
|
|
|
|
|
// @TODO Fix functional calls in 'select' queries
|
2019-04-05 20:46:07 -04:00
|
|
|
}
|
|
|
|
|
2019-04-09 14:13:37 -04:00
|
|
|
// Runs a basic sql query on the database
|
|
|
|
// fn query(&self, query: &str) -> Result<(), ()>;
|
2019-04-05 20:46:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_quote_identifier() {
|
2019-04-09 14:13:37 -04:00
|
|
|
let driver = DefaultDriver::new();
|
2019-04-05 20:46:07 -04:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
driver.quote_identifier("foo, bar, baz"),
|
|
|
|
r#""foo","bar","baz""#
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
driver.quote_identifier("foo.bar, baz, fizz"),
|
|
|
|
r#""foo"."bar","baz","fizz""#
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_quote_identifiers() {
|
2019-04-09 14:13:37 -04:00
|
|
|
let driver = DefaultDriver::new();
|
2019-04-05 20:46:07 -04:00
|
|
|
|
|
|
|
assert_eq!(
|
2019-04-11 11:44:06 -04:00
|
|
|
driver.quote_identifiers(vec![
|
|
|
|
"\tfoo. bar".to_string(),
|
|
|
|
"baz".to_string(),
|
|
|
|
"fizz.\n\tbuzz.baz".to_string(),
|
|
|
|
]),
|
2019-04-05 20:46:07 -04:00
|
|
|
vec![
|
|
|
|
r#""foo"."bar""#.to_string(),
|
|
|
|
r#""baz""#.to_string(),
|
|
|
|
r#""fizz"."buzz"."baz""#.to_string(),
|
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|