sqlite-wasm-connector/src/statement.rs

124 lines
3.8 KiB
Rust
Raw Normal View History

2015-06-12 14:23:18 -04:00
use ffi;
2015-05-29 11:24:01 -04:00
use libc::{c_double, c_int};
use std::marker::PhantomData;
2015-06-08 17:43:31 -04:00
use Result;
2015-05-29 11:24:01 -04:00
/// A prepared statement.
pub struct Statement<'l> {
2015-06-12 14:23:18 -04:00
raw: (*mut ffi::sqlite3_stmt, *mut ffi::sqlite3),
phantom: PhantomData<(ffi::sqlite3_stmt, &'l ffi::sqlite3)>,
2015-05-29 11:24:01 -04:00
}
/// A binding of a parameter of a prepared statement.
2015-05-29 11:24:01 -04:00
pub enum Binding<'l> {
Float(usize, f64),
Integer(usize, i64),
Text(usize, &'l str),
}
/// A value stored in a result row of a query.
2015-05-29 13:08:02 -04:00
pub trait Value {
/// Read the value stored in a specific column.
fn read(statement: &Statement, i: usize) -> Result<Self>;
2015-05-29 13:08:02 -04:00
}
2015-06-08 17:43:31 -04:00
/// A state of a prepared statement.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum State {
Done,
Row,
}
2015-05-29 11:24:01 -04:00
impl<'l> Statement<'l> {
/// Bind values to the parameters.
2015-05-29 13:34:48 -04:00
///
/// The leftmost parameter has the index 1.
2015-05-29 11:24:01 -04:00
pub fn bind(&mut self, bindings: &[Binding]) -> Result<()> {
for binding in bindings.iter() {
match *binding {
Binding::Float(i, value) => unsafe {
debug_assert!(i > 0, "the indexing starts from 1");
2015-06-12 14:23:18 -04:00
success!(self.raw.1, ffi::sqlite3_bind_double(self.raw.0, i as c_int,
2015-06-08 17:43:31 -04:00
value as c_double));
2015-05-29 11:24:01 -04:00
},
Binding::Integer(i, value) => unsafe {
debug_assert!(i > 0, "the indexing starts from 1");
2015-06-12 14:23:18 -04:00
success!(self.raw.1, ffi::sqlite3_bind_int64(self.raw.0, i as c_int,
value as ffi::sqlite3_int64));
2015-05-29 11:24:01 -04:00
},
Binding::Text(i, value) => unsafe {
debug_assert!(i > 0, "the indexing starts from 1");
2015-06-12 14:23:18 -04:00
success!(self.raw.1, ffi::sqlite3_bind_text(self.raw.0, i as c_int,
2015-06-08 17:43:31 -04:00
str_to_c_str!(value), -1, None));
2015-05-29 11:24:01 -04:00
},
}
}
Ok(())
}
/// Return the value stored in a specific column of the current result row.
///
/// The leftmost column has the index 0.
2015-05-29 13:08:02 -04:00
#[inline]
pub fn column<T: Value>(&self, i: usize) -> Result<T> {
2015-05-29 13:08:02 -04:00
<T as Value>::read(self, i)
}
/// Evaluate the statement.
2015-06-08 17:43:31 -04:00
pub fn step(&mut self) -> Result<State> {
2015-06-12 14:23:18 -04:00
match unsafe { ffi::sqlite3_step(self.raw.0) } {
ffi::SQLITE_DONE => Ok(State::Done),
ffi::SQLITE_ROW => Ok(State::Row),
2015-06-08 17:43:31 -04:00
code => failure!(self.raw.1, code),
}
2015-05-29 11:24:01 -04:00
}
/// Reset the statement.
2015-05-29 11:24:01 -04:00
#[inline]
pub fn reset(&mut self) -> Result<()> {
2015-06-12 14:23:18 -04:00
unsafe { success!(self.raw.1, ffi::sqlite3_reset(self.raw.0)) };
2015-05-29 11:24:01 -04:00
Ok(())
}
}
impl<'l> Drop for Statement<'l> {
#[inline]
fn drop(&mut self) {
2015-06-12 14:23:18 -04:00
unsafe { ffi::sqlite3_finalize(self.raw.0) };
2015-05-29 11:24:01 -04:00
}
}
2015-05-29 13:08:02 -04:00
impl Value for f64 {
fn read(statement: &Statement, i: usize) -> Result<f64> {
2015-06-12 14:23:18 -04:00
Ok(unsafe { ffi::sqlite3_column_double(statement.raw.0, i as c_int) as f64 })
2015-05-29 13:08:02 -04:00
}
}
impl Value for i64 {
fn read(statement: &Statement, i: usize) -> Result<i64> {
2015-06-12 14:23:18 -04:00
Ok(unsafe { ffi::sqlite3_column_int64(statement.raw.0, i as c_int) as i64 })
2015-05-29 13:08:02 -04:00
}
}
impl Value for String {
fn read(statement: &Statement, i: usize) -> Result<String> {
2015-05-29 13:08:02 -04:00
unsafe {
2015-06-12 14:23:18 -04:00
let pointer = ffi::sqlite3_column_text(statement.raw.0, i as c_int);
2015-05-29 13:08:02 -04:00
if pointer.is_null() {
raise!("cannot read a TEXT column");
}
Ok(c_str_to_string!(pointer))
}
}
}
2015-05-29 11:24:01 -04:00
#[inline]
2015-06-12 14:23:18 -04:00
pub fn new<'l>(raw1: *mut ffi::sqlite3, sql: &str) -> Result<Statement<'l>> {
2015-06-08 17:43:31 -04:00
let mut raw0 = 0 as *mut _;
unsafe {
2015-06-12 14:23:18 -04:00
success!(raw1, ffi::sqlite3_prepare(raw1, str_to_c_str!(sql), -1, &mut raw0, 0 as *mut _));
}
2015-06-08 17:43:31 -04:00
Ok(Statement { raw: (raw0, raw1), phantom: PhantomData })
2015-05-29 11:24:01 -04:00
}