diff --git a/src/lib.rs b/src/lib.rs index 692211f..6dd6ff4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -300,7 +300,12 @@ impl Client { /// Starts a new SELECT/DDL query. pub fn query(&self, query: &str) -> query::Query { - query::Query::new(self, query) + query::Query::new(self, query, "?") + } + + /// Starts a new SELECT/DDL query using the given arg for binding. + pub fn query_with_arg(&self, query: &str, arg: &str) -> query::Query { + query::Query::new(self, query, arg) } /// Starts a new WATCH query. diff --git a/src/query.rs b/src/query.rs index 5a03d17..727b6d2 100644 --- a/src/query.rs +++ b/src/query.rs @@ -23,10 +23,10 @@ pub struct Query { } impl Query { - pub(crate) fn new(client: &Client, template: &str) -> Self { + pub(crate) fn new(client: &Client, template: &str, arg: &str) -> Self { Self { client: client.clone(), - sql: SqlBuilder::new(template), + sql: SqlBuilder::new(template, arg), } } diff --git a/src/sql/mod.rs b/src/sql/mod.rs index edb42e7..c196b7a 100644 --- a/src/sql/mod.rs +++ b/src/sql/mod.rs @@ -25,8 +25,8 @@ pub(crate) enum Part { } impl SqlBuilder { - pub(crate) fn new(template: &str) -> Self { - let mut iter = template.split('?'); + pub(crate) fn new(template: &str, arg: &str) -> Self { + let mut iter = template.split(arg); let prefix = String::from(iter.next().unwrap()); let mut parts = vec![Part::Text(prefix)]; @@ -140,7 +140,7 @@ mod tests { #[test] fn bound_args() { - let mut sql = SqlBuilder::new("SELECT ?fields FROM test WHERE a = ? AND b < ?"); + let mut sql = SqlBuilder::new("SELECT ?fields FROM test WHERE a = ? AND b < ?", "?"); sql.bind_arg("foo"); sql.bind_arg(42); sql.bind_fields::(); @@ -153,7 +153,7 @@ mod tests { #[test] fn in_clause() { fn t(arg: &[&str], expected: &str) { - let mut sql = SqlBuilder::new("SELECT ?fields FROM test WHERE a IN ?"); + let mut sql = SqlBuilder::new("SELECT ?fields FROM test WHERE a IN ?", "?"); sql.bind_arg(arg); sql.bind_fields::(); assert_eq!(sql.finish().unwrap(), expected); @@ -175,7 +175,7 @@ mod tests { // See #18. #[test] fn question_marks_inside() { - let mut sql = SqlBuilder::new("SELECT 1 FROM test WHERE a IN ? AND b = ?"); + let mut sql = SqlBuilder::new("SELECT 1 FROM test WHERE a IN ? AND b = ?", "?"); sql.bind_arg(&["a?b", "c?"][..]); sql.bind_arg("a?"); assert_eq!( @@ -186,38 +186,38 @@ mod tests { #[test] fn option_as_null() { - let mut sql = SqlBuilder::new("SELECT 1 FROM test WHERE a = ?"); + let mut sql = SqlBuilder::new("SELECT 1 FROM test WHERE a = ?", "?"); sql.bind_arg(None::); assert_eq!(sql.finish().unwrap(), r"SELECT 1 FROM test WHERE a = NULL"); } #[test] fn option_as_value() { - let mut sql = SqlBuilder::new("SELECT 1 FROM test WHERE a = ?"); + let mut sql = SqlBuilder::new("SELECT 1 FROM test WHERE a = ?", "?"); sql.bind_arg(Some(1u32)); assert_eq!(sql.finish().unwrap(), r"SELECT 1 FROM test WHERE a = 1"); } #[test] fn failures() { - let mut sql = SqlBuilder::new("SELECT 1"); + let mut sql = SqlBuilder::new("SELECT 1", "?"); sql.bind_arg(42); let err = sql.finish().unwrap_err(); assert!(err.to_string().contains("all arguments are already bound")); - let mut sql = SqlBuilder::new("SELECT ?fields"); + let mut sql = SqlBuilder::new("SELECT ?fields", "?"); sql.bind_fields::(); let err = sql.finish().unwrap_err(); assert!(err .to_string() .contains("argument ?fields cannot be used with non-struct row types")); - let mut sql = SqlBuilder::new("SELECT a FROM test WHERE b = ? AND c = ?"); + let mut sql = SqlBuilder::new("SELECT a FROM test WHERE b = ? AND c = ?", "?"); sql.bind_arg(42); let err = sql.finish().unwrap_err(); assert!(err.to_string().contains("unbound query argument")); - let mut sql = SqlBuilder::new("SELECT ?fields FROM test WHERE b = ?"); + let mut sql = SqlBuilder::new("SELECT ?fields FROM test WHERE b = ?", "?"); sql.bind_arg(42); let err = sql.finish().unwrap_err(); assert!(err.to_string().contains("unbound query argument ?fields")); diff --git a/src/watch.rs b/src/watch.rs index 8833c13..f1dbcb4 100644 --- a/src/watch.rs +++ b/src/watch.rs @@ -84,7 +84,7 @@ impl Watch { Self { client, - sql: SqlBuilder::new(template), + sql: SqlBuilder::new(template, "?"), refresh: None, limit: None, _kind: Rows,