Make parameter_index return a Result<Option<_>> instead of squashing

string conversion errors into None.
This commit is contained in:
John Gallagher 2015-12-10 20:41:31 -05:00
parent 186cb5893b
commit b7468b2c4b

View File

@ -1,9 +1,9 @@
use std::ffi::CString;
use libc::c_int; use libc::c_int;
use super::ffi; use super::ffi;
use {SqliteResult, SqliteError, SqliteConnection, SqliteStatement, SqliteRows, SqliteRow}; use {SqliteResult, SqliteError, SqliteConnection, SqliteStatement, SqliteRows, SqliteRow,
str_to_cstring};
use types::ToSql; use types::ToSql;
impl SqliteConnection { impl SqliteConnection {
@ -65,17 +65,15 @@ impl<'conn> SqliteStatement<'conn> {
/// ///
/// # Failure /// # Failure
/// ///
/// Return None if `name` is invalid or if no matching parameter is found. /// Will return Err if `name` is invalid. Will return Ok(None) if the name
pub fn parameter_index(&self, name: &str) -> Option<i32> { /// is valid but not a bound parameter of this statement.
unsafe { pub fn parameter_index(&self, name: &str) -> SqliteResult<Option<i32>> {
CString::new(name).ok().and_then(|c_name| { let c_name = try!(str_to_cstring(name));
match ffi::sqlite3_bind_parameter_index(self.stmt, c_name.as_ptr()) { let c_index = unsafe { ffi::sqlite3_bind_parameter_index(self.stmt, c_name.as_ptr()) };
0 => None, // A zero is returned if no matching parameter is found. Ok(match c_index {
n => Some(n), 0 => None, // A zero is returned if no matching parameter is found.
} n => Some(n),
}) })
}
} }
/// Execute the prepared statement with named parameter(s). /// Execute the prepared statement with named parameter(s).
@ -98,8 +96,8 @@ impl<'conn> SqliteStatement<'conn> {
/// Will return `Err` if binding parameters fails, the executed statement returns rows (in /// Will return `Err` if binding parameters fails, the executed statement returns rows (in
/// which case `query` should be used instead), or the underling SQLite call fails. /// which case `query` should be used instead), or the underling SQLite call fails.
pub fn execute_named(&mut self, params: &[(&str, &ToSql)]) -> SqliteResult<c_int> { pub fn execute_named(&mut self, params: &[(&str, &ToSql)]) -> SqliteResult<c_int> {
try!(self.bind_named_parameters(params));
unsafe { unsafe {
try!(self.bind_named_parameters(params));
self.execute_() self.execute_()
} }
} }
@ -128,20 +126,17 @@ impl<'conn> SqliteStatement<'conn> {
params: &[(&str, &ToSql)]) params: &[(&str, &ToSql)])
-> SqliteResult<SqliteRows<'a>> { -> SqliteResult<SqliteRows<'a>> {
self.reset_if_needed(); self.reset_if_needed();
try!(self.bind_named_parameters(params));
unsafe {
try!(self.bind_named_parameters(params));
}
self.needs_reset = true; self.needs_reset = true;
Ok(SqliteRows::new(self)) Ok(SqliteRows::new(self))
} }
unsafe fn bind_named_parameters(&mut self, params: &[(&str, &ToSql)]) -> SqliteResult<()> { fn bind_named_parameters(&mut self, params: &[(&str, &ToSql)]) -> SqliteResult<()> {
// Always check that the number of parameters is correct. // Always check that the number of parameters is correct.
assert!(params.len() as c_int == ffi::sqlite3_bind_parameter_count(self.stmt), assert!(params.len() as c_int == unsafe { ffi::sqlite3_bind_parameter_count(self.stmt) },
"incorrect number of parameters to query(): expected {}, got {}", "incorrect number of parameters to query(): expected {}, got {}",
ffi::sqlite3_bind_parameter_count(self.stmt), unsafe { ffi::sqlite3_bind_parameter_count(self.stmt) },
params.len()); params.len());
// In debug, also sanity check that we got distinct parameter names. // In debug, also sanity check that we got distinct parameter names.
@ -158,11 +153,14 @@ impl<'conn> SqliteStatement<'conn> {
"named parameters must be unique"); "named parameters must be unique");
for &(name, value) in params { for &(name, value) in params {
let i = try!(self.parameter_index(name).ok_or(SqliteError { if let Some(i) = try!(self.parameter_index(name)) {
code: ffi::SQLITE_MISUSE, try!(self.conn.decode_result(unsafe { value.bind_parameter(self.stmt, i) }));
message: format!("Invalid parameter name: {}", name), } else {
})); return Err(SqliteError {
try!(self.conn.decode_result(value.bind_parameter(self.stmt, i))); code: ffi::SQLITE_MISUSE,
message: format!("Invalid parameter name: {}", name),
});
}
} }
Ok(()) Ok(())
} }