//! Drivers //! //! Drivers represent a connection to a specific type of database engine use std::fmt; #[cfg(feature = "postgres")] mod postgres; #[cfg(feature = "sqlite")] mod sqlite; #[cfg(feature = "mysql")] mod mysql; #[cfg(feature = "mssql")] mod mssql; #[derive(Debug)] struct Connection; /// Result for a db query #[derive(Debug)] struct QueryResult; struct DriverBase { escape_char_open: char, escape_char_close: char, has_truncate: bool, } /// 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` fn quote_identifiers(&self, identifiers: Vec) -> Vec { let mut output: Vec = vec![]; for identifier in identifiers { output.push(self.quote_identifier(&identifier).to_string()); } output } /// Quote the identifiers passed, so the database does not /// normalize the identifiers (eg, table, column, etc.) fn quote_identifier(&self, identifier: &str) -> String { let mut identifier = &mut String::from(identifier); // If the identifier is actually a list, // recurse to quote each identifier in the list if identifier.contains(",") { let mut quoted_parts: Vec = vec![]; for part in identifier.split(",") { let new_part = part.trim(); let new_part = &self.quote_identifier(new_part); quoted_parts.push(new_part.to_owned()); } // This was the only way I could figure to get // around mutable string reference scope hell identifier.replace_range(.., &mut quoted_parts.join(",")); } let (open_char, close_char) = self._quotes(); let mut trimmed_hiers: Vec = vec![]; for hier in identifier.split(".") { let mut hier = &mut hier.trim(); if hier.starts_with(open_char) && hier.ends_with(close_char) { trimmed_hiers.push(hier.to_string()); } else { let mut hier = format!("{}{}{}", open_char, hier, close_char); trimmed_hiers.push(hier.to_string()); } } trimmed_hiers.join(".") } /// Runs a basic sql query on the database fn query(&self, query: &str) -> Result<(), ()>; } #[cfg(test)] mod tests { use super::*; #[derive(Debug)] struct TestDriver; impl DatabaseDriver for TestDriver { fn query(&self, _query: &str) -> Result<(), ()> { Ok(()) } } #[test] fn test_quote_identifier() { let driver = TestDriver {}; 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() { let driver = TestDriver {}; assert_eq!( driver.quote_identifiers(vec![ "\tfoo. bar".to_string(), "baz".to_string(), "fizz.\n\tbuzz.baz".to_string(), ]), vec![ r#""foo"."bar""#.to_string(), r#""baz""#.to_string(), r#""fizz"."buzz"."baz""#.to_string(), ] ); } }