From 42515bc5ecf9d810fddc84693c74b9f5fc8d3f6b Mon Sep 17 00:00:00 2001 From: Ivan Ukhov Date: Mon, 3 Aug 2015 08:41:23 -0400 Subject: [PATCH] Add a function to read the current state of a statement --- src/statement.rs | 65 +++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/src/statement.rs b/src/statement.rs index 3ab623a..f17c6f4 100644 --- a/src/statement.rs +++ b/src/statement.rs @@ -6,6 +6,7 @@ use {Result, Type, Value}; /// A prepared statement. pub struct Statement<'l> { + state: Option, raw: (*mut ffi::sqlite3_stmt, *mut ffi::sqlite3), phantom: PhantomData<(ffi::sqlite3_stmt, &'l ffi::sqlite3)>, } @@ -15,37 +16,64 @@ pub struct Statement<'l> { pub enum State { /// There is a row available for reading. Row, - /// There is nothing else to read. + /// The statement has been entirely evaluated. Done, } -/// A type suitable for binding to a parameter of a prepared statement. +/// A type suitable for binding to a prepared statement. pub trait Bindable { - /// Bind to a particular parameter. + /// Bind to a parameter. /// /// The leftmost parameter has the index 1. fn bind(&self, &mut Statement, usize) -> Result<()>; } -/// A type suitable for reading from a column of a prepared statement. +/// A type suitable for reading from a prepared statement. pub trait Readable { - /// Read from a particular column. + /// Read from a column. /// /// The leftmost column has the index 0. fn read(&Statement, usize) -> Result; } impl<'l> Statement<'l> { + /// Bind a value to a parameter. + /// + /// The leftmost parameter has the index 1. + #[inline] + pub fn bind(&mut self, i: usize, parameter: T) -> Result<()> { + parameter.bind(self, i) + } + /// Return the number of columns. #[inline] pub fn columns(&self) -> usize { unsafe { ffi::sqlite3_column_count(self.raw.0) as usize } } + /// Advance the statement to the next state. + /// + /// The function should be called multiple times until `State::Done` is + /// reached in order to evaluate the statement entirely. + pub fn step(&mut self) -> Result { + let state = match unsafe { ffi::sqlite3_step(self.raw.0) } { + ffi::SQLITE_ROW => State::Row, + ffi::SQLITE_DONE => State::Done, + code => error!(self.raw.1, code), + }; + self.state = Some(state); + Ok(state) + } + + /// Return the current state. + #[inline] + pub fn state(&self) -> Option { + self.state + } + /// Return the type of a column. /// /// The type is revealed after the first step has been taken. - #[inline] pub fn kind(&self, i: usize) -> Type { match unsafe { ffi::sqlite3_column_type(self.raw.0, i as c_int) } { ffi::SQLITE_BLOB => Type::Binary, @@ -57,15 +85,7 @@ impl<'l> Statement<'l> { } } - /// Bind the parameter at a specific location. - /// - /// The leftmost location has the index 1. - #[inline] - pub fn bind(&mut self, i: usize, parameter: T) -> Result<()> { - parameter.bind(self, i) - } - - /// Read the value stored in a specific column. + /// Read a value from a column. /// /// The leftmost column has the index 0. #[inline] @@ -73,22 +93,11 @@ impl<'l> Statement<'l> { Readable::read(self, i) } - /// Evaluate the statement one step at a time. - /// - /// The function should be called multiple times until `State::Done` is - /// reached in order to evaluate the statement entirely. - pub fn step(&mut self) -> Result { - match unsafe { ffi::sqlite3_step(self.raw.0) } { - ffi::SQLITE_DONE => Ok(State::Done), - ffi::SQLITE_ROW => Ok(State::Row), - code => error!(self.raw.1, code), - } - } - /// Reset the statement. #[inline] pub fn reset(&mut self) -> Result<()> { unsafe { ok!(self.raw.1, ffi::sqlite3_reset(self.raw.0)) }; + self.state = None; Ok(()) } } @@ -242,5 +251,5 @@ pub fn new<'l, T: AsRef>(raw1: *mut ffi::sqlite3, statement: T) -> Result