mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-26 19:41:37 +08:00
commit
b3bb0a1e83
@ -77,6 +77,9 @@ pub enum Error {
|
|||||||
|
|
||||||
/// Error available for the implementors of the `ToSql` trait.
|
/// Error available for the implementors of the `ToSql` trait.
|
||||||
ToSqlConversionFailure(Box<error::Error + Send + Sync>),
|
ToSqlConversionFailure(Box<error::Error + Send + Sync>),
|
||||||
|
|
||||||
|
/// Error when the SQL is not a `SELECT`, is not read-only.
|
||||||
|
InvalidQuery,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<str::Utf8Error> for Error {
|
impl From<str::Utf8Error> for Error {
|
||||||
@ -132,6 +135,7 @@ impl fmt::Display for Error {
|
|||||||
#[cfg(feature = "functions")]
|
#[cfg(feature = "functions")]
|
||||||
Error::UserFunctionError(ref err) => err.fmt(f),
|
Error::UserFunctionError(ref err) => err.fmt(f),
|
||||||
Error::ToSqlConversionFailure(ref err) => err.fmt(f),
|
Error::ToSqlConversionFailure(ref err) => err.fmt(f),
|
||||||
|
Error::InvalidQuery => write!(f, "Query is not read-only"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,6 +164,7 @@ impl error::Error for Error {
|
|||||||
#[cfg(feature = "functions")]
|
#[cfg(feature = "functions")]
|
||||||
Error::UserFunctionError(ref err) => err.description(),
|
Error::UserFunctionError(ref err) => err.description(),
|
||||||
Error::ToSqlConversionFailure(ref err) => err.description(),
|
Error::ToSqlConversionFailure(ref err) => err.description(),
|
||||||
|
Error::InvalidQuery => "query is not read-only",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +183,8 @@ impl error::Error for Error {
|
|||||||
Error::InvalidColumnName(_) |
|
Error::InvalidColumnName(_) |
|
||||||
Error::InvalidColumnType(_, _) |
|
Error::InvalidColumnType(_, _) |
|
||||||
Error::InvalidPath(_) |
|
Error::InvalidPath(_) |
|
||||||
Error::StatementChangedRows(_) => None,
|
Error::StatementChangedRows(_) |
|
||||||
|
Error::InvalidQuery => None,
|
||||||
|
|
||||||
#[cfg(feature = "functions")]
|
#[cfg(feature = "functions")]
|
||||||
Error::InvalidFunctionParameterType(_, _) => None,
|
Error::InvalidFunctionParameterType(_, _) => None,
|
||||||
|
@ -83,6 +83,23 @@ impl RawStatement {
|
|||||||
self.0 = ptr::null_mut();
|
self.0 = ptr::null_mut();
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bundled")]
|
||||||
|
pub fn readonly(&self) -> bool {
|
||||||
|
unsafe { ffi::sqlite3_stmt_readonly(self.0) != 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bundled")]
|
||||||
|
pub fn expanded_sql(&self) -> Option<&CStr> {
|
||||||
|
unsafe {
|
||||||
|
let ptr = ffi::sqlite3_expanded_sql(self.0);
|
||||||
|
if ptr.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(CStr::from_ptr(ptr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for RawStatement {
|
impl Drop for RawStatement {
|
||||||
|
@ -154,6 +154,7 @@ impl<'conn> Statement<'conn> {
|
|||||||
///
|
///
|
||||||
/// Will return `Err` if binding parameters fails.
|
/// Will return `Err` if binding parameters fails.
|
||||||
pub fn query<'a>(&'a mut self, params: &[&ToSql]) -> Result<Rows<'a>> {
|
pub fn query<'a>(&'a mut self, params: &[&ToSql]) -> Result<Rows<'a>> {
|
||||||
|
try!(self.check_readonly());
|
||||||
try!(self.bind_parameters(params));
|
try!(self.bind_parameters(params));
|
||||||
Ok(Rows::new(self))
|
Ok(Rows::new(self))
|
||||||
}
|
}
|
||||||
@ -181,6 +182,7 @@ impl<'conn> Statement<'conn> {
|
|||||||
///
|
///
|
||||||
/// Will return `Err` if binding parameters fails.
|
/// Will return `Err` if binding parameters fails.
|
||||||
pub fn query_named<'a>(&'a mut self, params: &[(&str, &ToSql)]) -> Result<Rows<'a>> {
|
pub fn query_named<'a>(&'a mut self, params: &[(&str, &ToSql)]) -> Result<Rows<'a>> {
|
||||||
|
try!(self.check_readonly());
|
||||||
try!(self.bind_parameters_named(params));
|
try!(self.bind_parameters_named(params));
|
||||||
Ok(Rows::new(self))
|
Ok(Rows::new(self))
|
||||||
}
|
}
|
||||||
@ -465,6 +467,27 @@ impl<'conn> Statement<'conn> {
|
|||||||
mem::swap(&mut stmt, &mut self.stmt);
|
mem::swap(&mut stmt, &mut self.stmt);
|
||||||
self.conn.decode_result(stmt.finalize())
|
self.conn.decode_result(stmt.finalize())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "bundled"))]
|
||||||
|
fn check_readonly(&self) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bundled")]
|
||||||
|
fn check_readonly(&self) -> Result<()> {
|
||||||
|
if !self.stmt.readonly() {
|
||||||
|
return Err(Error::InvalidQuery);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a string containing the SQL text of prepared statement with bound parameters expanded.
|
||||||
|
#[cfg(feature = "bundled")]
|
||||||
|
pub fn expanded_sql(&self) -> Option<&str> {
|
||||||
|
unsafe {
|
||||||
|
self.stmt.expanded_sql().map(|s| str::from_utf8_unchecked(s.to_bytes()))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'conn> Into<RawStatement> for Statement<'conn> {
|
impl<'conn> Into<RawStatement> for Statement<'conn> {
|
||||||
@ -801,4 +824,13 @@ mod test {
|
|||||||
let y: Result<i64> = stmt.query_row(&[], |r| r.get("y"));
|
let y: Result<i64> = stmt.query_row(&[], |r| r.get("y"));
|
||||||
assert_eq!(3i64, y.unwrap());
|
assert_eq!(3i64, y.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "bundled")]
|
||||||
|
fn test_expanded_sql() {
|
||||||
|
let db = Connection::open_in_memory().unwrap();
|
||||||
|
let stmt = db.prepare("SELECT ?").unwrap();
|
||||||
|
stmt.bind_parameter(&1, 1).unwrap();
|
||||||
|
assert_eq!(Some("SELECT 1"), stmt.expanded_sql());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user