diff --git a/src/database.rs b/src/database.rs index 0b42398..0a97117 100644 --- a/src/database.rs +++ b/src/database.rs @@ -11,7 +11,7 @@ pub struct Database { phantom: PhantomData, } -/// A callback triggered when an operation fails due to concurrent activity. If +/// A callback triggered when the database is busy and rejects an operation. If /// the callback returns `true`, the operation will be repeated. pub type BusyCallback<'l> = FnMut(usize) -> bool + 'l; @@ -20,7 +20,7 @@ pub type BusyCallback<'l> = FnMut(usize) -> bool + 'l; pub type ExecuteCallback<'l> = FnMut(Vec<(String, String)>) -> bool + 'l; impl Database { - /// Open a database. + /// Open a database connect. pub fn open(path: &Path) -> Result { let mut raw = 0 as *mut _; unsafe { @@ -29,50 +29,53 @@ impl Database { Ok(Database { raw: raw, phantom: PhantomData }) } - /// Execute an SQL statement. + /// Execute an SQL query. pub fn execute<'l>(&self, sql: &str, callback: Option<&mut ExecuteCallback<'l>>) -> Result<()> { - unsafe { - match callback { - Some(callback) => { - let mut callback = Box::new(callback); + match callback { + Some(callback) => unsafe { + let mut callback = Box::new(callback); success!(self, raw::sqlite3_exec(self.raw, str_to_c_str!(sql), Some(execute_callback), &mut callback as *mut _ as *mut _, 0 as *mut _)); - }, - None => { - success!(self, raw::sqlite3_exec(self.raw, str_to_c_str!(sql), None, - 0 as *mut _, 0 as *mut _)); - }, - } + }, + None => unsafe { + success!(self, raw::sqlite3_exec(self.raw, str_to_c_str!(sql), None, + 0 as *mut _, 0 as *mut _)); + }, } Ok(()) } - /// Create a prepared statement. + /// Compile an SQL statement. #[inline] - pub fn prepare_statement<'l>(&'l self, sql: &str) -> Result> { + pub fn prepare<'l>(&'l self, sql: &str) -> Result> { ::statement::new(self, sql) } - /// Set a callback for handling failures due to concurrent activity. + /// Set a callback to handle rejected operations when the database is busy. pub fn set_busy_handler(&mut self, callback: Option<&mut BusyCallback>) -> Result<()> { - unsafe { - match callback { - Some(callback) => { - let mut callback = Box::new(callback); - success!(self, raw::sqlite3_busy_handler(self.raw, Some(busy_callback), - &mut callback as *mut _ as *mut _)); - }, - None => { - success!(self, raw::sqlite3_busy_handler(self.raw, None, 0 as *mut _)); - }, - } + match callback { + Some(callback) => unsafe { + let mut callback = Box::new(callback); + success!(self, raw::sqlite3_busy_handler(self.raw, Some(busy_callback), + &mut callback as *mut _ as *mut _)); + }, + None => unsafe { + success!(self, raw::sqlite3_busy_handler(self.raw, None, 0 as *mut _)); + }, } Ok(()) } + + /// Set a timeout before rejecting an operation when the database is busy. + #[inline] + pub fn set_busy_timeout(&mut self, milliseconds: usize) -> Result<()> { + unsafe { success!(self, raw::sqlite3_busy_timeout(self.raw, milliseconds as c_int)) }; + Ok(()) + } } impl Drop for Database { diff --git a/src/statement.rs b/src/statement.rs index 0a2d1f1..4e03bae 100644 --- a/src/statement.rs +++ b/src/statement.rs @@ -10,58 +10,60 @@ pub struct Statement<'l> { phantom: PhantomData<(&'l raw::sqlite3, raw::sqlite3_stmt)>, } -/// A binding of a prepared statement. +/// A binding of a parameter of a prepared statement. pub enum Binding<'l> { Float(usize, f64), Integer(usize, i64), Text(usize, &'l str), } -/// A value stored in a prepared statement. +/// A value stored in a result row of a query. pub trait Value { - /// Read the value at a specific column. + /// Read the value stored in a specific column. fn read(statement: &Statement, i: usize) -> Result; } impl<'l> Statement<'l> { - /// Assign values to the placeholders. + /// Bind values to the parameters. /// - /// The leftmost parameter has an index of 1. + /// The leftmost parameter has the index 1. 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 indexation starts from 1"); + debug_assert!(i > 0, "the indexing starts from 1"); success!(raw::sqlite3_bind_double(self.raw, i as c_int, value as c_double)); }, Binding::Integer(i, value) => unsafe { - debug_assert!(i > 0, "the indexation starts from 1"); + debug_assert!(i > 0, "the indexing starts from 1"); success!(raw::sqlite3_bind_int64(self.raw, i as c_int, value as raw::sqlite3_int64)); }, Binding::Text(i, value) => unsafe { - debug_assert!(i > 0, "the indexation starts from 1"); - success!(raw::sqlite3_bind_text(self.raw, i as c_int, str_to_c_str!(value), - -1, None)); + debug_assert!(i > 0, "the indexing starts from 1"); + success!(raw::sqlite3_bind_text(self.raw, i as c_int, str_to_c_str!(value), -1, + None)); }, } } Ok(()) } - /// Return the value of a column. + /// Return the value stored in a specific column of the current result row. + /// + /// The leftmost column has the index 0. #[inline] pub fn column(&self, i: usize) -> Result { ::read(self, i) } - /// Take a step. + /// Evaluate the statement. #[inline] pub fn step(&mut self) -> ResultCode { unsafe { ::result::code_from_raw(raw::sqlite3_step(self.raw)) } } - /// Reset. + /// Reset the statement. #[inline] pub fn reset(&mut self) -> Result<()> { unsafe { success!(raw::sqlite3_reset(self.raw)) }; diff --git a/tests/lib.rs b/tests/lib.rs index 67f6008..684f557 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -25,7 +25,7 @@ fn workflow() { { let sql = r#"INSERT INTO `users` (id, name, age) VALUES (?, ?, ?);"#; - let mut statement = ok!(database.prepare_statement(sql)); + let mut statement = ok!(database.prepare(sql)); ok!(statement.bind(&[Integer(1, 1), Text(2, "Alice"), Float(3, 20.99)])); assert!(statement.step() == ResultCode::Done); } @@ -46,7 +46,7 @@ fn workflow() { { let sql = r#"SELECT * FROM `users`;"#; - let mut statement = ok!(database.prepare_statement(sql)); + let mut statement = ok!(database.prepare(sql)); assert!(statement.step() == ResultCode::Row); assert!(ok!(statement.column::(0)) == 1); assert!(ok!(statement.column::(1)) == String::from("Alice"));