From 19a1856253d54466bea0cc993a83a6d6b028fc18 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Wed, 26 Apr 2017 17:25:40 -0700 Subject: [PATCH] Part 2: take a dependency on rusqlite for query arguments. --- query-translator/tests/translate.rs | 6 ++--- sql/Cargo.toml | 5 ++++ sql/src/lib.rs | 37 +++++++++++++++++++---------- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/query-translator/tests/translate.rs b/query-translator/tests/translate.rs index a13c2fa7..1342acf9 100644 --- a/query-translator/tests/translate.rs +++ b/query-translator/tests/translate.rs @@ -76,8 +76,8 @@ fn prepopulated_schema() -> Schema { prepopulated_typed_schema(ValueType::String) } -fn make_arg(name: &'static str, value: &'static str) -> (String, Rc) { - (name.to_string(), Rc::new(value.to_string())) +fn make_arg(name: &'static str, value: &'static str) -> (String, Rc) { + (name.to_string(), Rc::new(mentat_sql::Value::Text(value.to_string()))) } #[test] @@ -550,4 +550,4 @@ fn test_complex_nested_or_join_type_projection() { AS `c00` \ LIMIT 1"); assert_eq!(args, vec![]); -} \ No newline at end of file +} diff --git a/sql/Cargo.toml b/sql/Cargo.toml index 868d07e4..abca4fa2 100644 --- a/sql/Cargo.toml +++ b/sql/Cargo.toml @@ -7,5 +7,10 @@ workspace = ".." error-chain = "0.8.1" ordered-float = "0.4.0" +[dependencies.rusqlite] +version = "0.10.1" +# System sqlite might be very old. +features = ["bundled", "limits"] + [dependencies.mentat_core] path = "../core" diff --git a/sql/src/lib.rs b/sql/src/lib.rs index 292ddd3d..08197954 100644 --- a/sql/src/lib.rs +++ b/sql/src/lib.rs @@ -11,6 +11,8 @@ #[macro_use] extern crate error_chain; extern crate ordered_float; +extern crate rusqlite; + extern crate mentat_core; use std::rc::Rc; @@ -19,6 +21,8 @@ use ordered_float::OrderedFloat; use mentat_core::TypedValue; +pub use rusqlite::types::Value; + error_chain! { types { Error, ErrorKind, ResultExt, Result; @@ -47,7 +51,7 @@ pub struct SQLQuery { pub sql: String, /// These will eventually perhaps be rusqlite `ToSql` instances. - pub args: Vec<(String, Rc)>, + pub args: Vec<(String, Rc)>, } /// Gratefully based on Diesel's QueryBuilder trait: @@ -88,7 +92,7 @@ pub struct SQLiteQueryBuilder { arg_prefix: String, arg_counter: i64, - args: Vec<(String, Rc)>, + args: Vec<(String, Rc)>, } impl SQLiteQueryBuilder { @@ -105,7 +109,7 @@ impl SQLiteQueryBuilder { } } - fn push_static_arg(&mut self, val: Rc) { + fn push_static_arg(&mut self, val: Rc) { let arg = format!("{}{}", self.arg_prefix, self.arg_counter); self.arg_counter = self.arg_counter + 1; self.push_named_arg(arg.as_str()); @@ -136,11 +140,16 @@ impl QueryBuilder for SQLiteQueryBuilder { &Boolean(v) => self.push_sql(if v { "1" } else { "0" }), &Long(v) => self.push_sql(v.to_string().as_str()), &Double(OrderedFloat(v)) => self.push_sql(v.to_string().as_str()), - - // These are both `Rc`. We can just clone an `Rc`, but we - // must make a new single `String`, wrapped in an `Rc`, for keywords. - &String(ref s) => self.push_static_arg(s.clone()), - &Keyword(ref s) => self.push_static_arg(Rc::new(s.as_ref().to_string())), + // These are both `Rc`. Unfortunately, we can't use that fact when + // turning these into rusqlite Values. + &String(ref s) => { + let v = Rc::new(rusqlite::types::Value::Text(s.as_ref().clone())); + self.push_static_arg(v); + }, + &Keyword(ref s) => { + let v = Rc::new(rusqlite::types::Value::Text(s.as_ref().to_string())); + self.push_static_arg(v); + }, } Ok(()) } @@ -180,6 +189,10 @@ impl QueryBuilder for SQLiteQueryBuilder { mod tests { use super::*; + fn string_arg(s: &str) -> Rc { + Rc::new(rusqlite::types::Value::Text(s.to_string())) + } + #[test] fn test_sql() { let mut s = SQLiteQueryBuilder::new(); @@ -188,14 +201,14 @@ mod tests { s.push_sql(" WHERE "); s.push_identifier("bar").unwrap(); s.push_sql(" = "); - s.push_static_arg(Rc::new("frobnicate".to_string())); + s.push_static_arg(string_arg("frobnicate")); s.push_sql(" OR "); - s.push_static_arg(Rc::new("swoogle".to_string())); + s.push_static_arg(string_arg("swoogle")); let q = s.finish(); assert_eq!(q.sql.as_str(), "SELECT `foo` WHERE `bar` = $v0 OR $v1"); assert_eq!(q.args, - vec![("$v0".to_string(), Rc::new("frobnicate".to_string())), - ("$v1".to_string(), Rc::new("swoogle".to_string()))]); + vec![("$v0".to_string(), string_arg("frobnicate")), + ("$v1".to_string(), string_arg("swoogle"))]); } }