diff --git a/query-translator/src/types.rs b/query-translator/src/types.rs index d149455a..7484dac7 100644 --- a/query-translator/src/types.rs +++ b/query-translator/src/types.rs @@ -24,8 +24,9 @@ use mentat_query_algebrizer::{ SourceAlias, }; +use mentat_sql; + use mentat_sql::{ - BuildQueryError, BuildQueryResult, QueryBuilder, QueryFragment, @@ -268,7 +269,7 @@ impl QueryFragment for SelectQuery { } impl SelectQuery { - pub fn to_sql_query(&self) -> Result { + pub fn to_sql_query(&self) -> mentat_sql::Result { let mut builder = SQLiteQueryBuilder::new(); self.push_sql(&mut builder).map(|_| builder.finish()) } diff --git a/sql/Cargo.toml b/sql/Cargo.toml index 0a15dde6..d6e57d77 100644 --- a/sql/Cargo.toml +++ b/sql/Cargo.toml @@ -4,6 +4,7 @@ version = "0.0.1" workspace = ".." [dependencies] +error-chain = "0.9.0" ordered-float = "0.4.0" [dependencies.mentat_core] diff --git a/sql/src/lib.rs b/sql/src/lib.rs index 62fb8f11..35dfface 100644 --- a/sql/src/lib.rs +++ b/sql/src/lib.rs @@ -8,23 +8,35 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. +#[macro_use] +extern crate error_chain; extern crate ordered_float; extern crate mentat_core; -use std::error::Error; - use ordered_float::OrderedFloat; use mentat_core::TypedValue; -pub type BuildQueryError = Box; -pub type BuildQueryResult = Result<(), BuildQueryError>; +error_chain! { + types { + Error, ErrorKind, ResultExt, Result; + } -pub enum BindParamError { - InvalidParameterName(String), - BindParamCouldBeGenerated(String), + errors { + InvalidParameterName(name: String) { + description("invalid parameter name") + display("invalid parameter name: '{}'", name) + } + + BindParamCouldBeGenerated(name: String) { + description("parameter name could be generated") + display("parameter name could be generated: '{}'", name) + } + } } +pub type BuildQueryResult = Result<()>; + /// We want to accumulate values that will later be substituted into a SQL statement execution. /// This struct encapsulates the generated string and the _initial_ argument list. /// Additional user-supplied argument bindings, with their placeholders accumulated via @@ -42,7 +54,7 @@ pub trait QueryBuilder { fn push_sql(&mut self, sql: &str); fn push_identifier(&mut self, identifier: &str) -> BuildQueryResult; fn push_typed_value(&mut self, value: &TypedValue) -> BuildQueryResult; - fn push_bind_param(&mut self, name: &str) -> Result<(), BindParamError>; + fn push_bind_param(&mut self, name: &str) -> BuildQueryResult; fn finish(self) -> SQLQuery; } @@ -134,16 +146,16 @@ impl QueryBuilder for SQLiteQueryBuilder { /// returns an `InvalidParameterName` error result. /// Callers should make sure that the name doesn't overlap with generated parameter names. If /// it does, `BindParamCouldBeGenerated` is the error. - fn push_bind_param(&mut self, name: &str) -> Result<(), BindParamError> { + fn push_bind_param(&mut self, name: &str) -> BuildQueryResult { // Do some validation first. // This is not free, but it's probably worth it for now. if !name.chars().all(char::is_alphanumeric) { - return Err(BindParamError::InvalidParameterName(name.to_string())); + bail!(ErrorKind::InvalidParameterName(name.to_string())); } if name.starts_with(self.arg_prefix.as_str()) && name.chars().skip(self.arg_prefix.len()).all(char::is_numeric) { - return Err(BindParamError::BindParamCouldBeGenerated(name.to_string())); + bail!(ErrorKind::BindParamCouldBeGenerated(name.to_string())); } self.push_sql("$");