mirror of
https://github.com/fluencelabs/sqlite-wasm-connector
synced 2025-04-13 03:26:03 +00:00
Rename a couple of functions; add set_busy_timeout
This commit is contained in:
parent
2698514218
commit
bfa3a976c8
@ -11,7 +11,7 @@ pub struct Database {
|
|||||||
phantom: PhantomData<raw::sqlite3>,
|
phantom: PhantomData<raw::sqlite3>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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.
|
/// the callback returns `true`, the operation will be repeated.
|
||||||
pub type BusyCallback<'l> = FnMut(usize) -> bool + 'l;
|
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;
|
pub type ExecuteCallback<'l> = FnMut(Vec<(String, String)>) -> bool + 'l;
|
||||||
|
|
||||||
impl Database {
|
impl Database {
|
||||||
/// Open a database.
|
/// Open a database connect.
|
||||||
pub fn open(path: &Path) -> Result<Database> {
|
pub fn open(path: &Path) -> Result<Database> {
|
||||||
let mut raw = 0 as *mut _;
|
let mut raw = 0 as *mut _;
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -29,48 +29,51 @@ impl Database {
|
|||||||
Ok(Database { raw: raw, phantom: PhantomData })
|
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>>)
|
pub fn execute<'l>(&self, sql: &str, callback: Option<&mut ExecuteCallback<'l>>)
|
||||||
-> Result<()> {
|
-> Result<()> {
|
||||||
|
|
||||||
unsafe {
|
|
||||||
match callback {
|
match callback {
|
||||||
Some(callback) => {
|
Some(callback) => unsafe {
|
||||||
let mut callback = Box::new(callback);
|
let mut callback = Box::new(callback);
|
||||||
success!(self, raw::sqlite3_exec(self.raw, str_to_c_str!(sql),
|
success!(self, raw::sqlite3_exec(self.raw, str_to_c_str!(sql),
|
||||||
Some(execute_callback),
|
Some(execute_callback),
|
||||||
&mut callback as *mut _ as *mut _,
|
&mut callback as *mut _ as *mut _,
|
||||||
0 as *mut _));
|
0 as *mut _));
|
||||||
},
|
},
|
||||||
None => {
|
None => unsafe {
|
||||||
success!(self, raw::sqlite3_exec(self.raw, str_to_c_str!(sql), None,
|
success!(self, raw::sqlite3_exec(self.raw, str_to_c_str!(sql), None,
|
||||||
0 as *mut _, 0 as *mut _));
|
0 as *mut _, 0 as *mut _));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a prepared statement.
|
/// Compile an SQL statement.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn prepare_statement<'l>(&'l self, sql: &str) -> Result<Statement<'l>> {
|
pub fn prepare<'l>(&'l self, sql: &str) -> Result<Statement<'l>> {
|
||||||
::statement::new(self, sql)
|
::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<()> {
|
pub fn set_busy_handler(&mut self, callback: Option<&mut BusyCallback>) -> Result<()> {
|
||||||
unsafe {
|
|
||||||
match callback {
|
match callback {
|
||||||
Some(callback) => {
|
Some(callback) => unsafe {
|
||||||
let mut callback = Box::new(callback);
|
let mut callback = Box::new(callback);
|
||||||
success!(self, raw::sqlite3_busy_handler(self.raw, Some(busy_callback),
|
success!(self, raw::sqlite3_busy_handler(self.raw, Some(busy_callback),
|
||||||
&mut callback as *mut _ as *mut _));
|
&mut callback as *mut _ as *mut _));
|
||||||
},
|
},
|
||||||
None => {
|
None => unsafe {
|
||||||
success!(self, raw::sqlite3_busy_handler(self.raw, None, 0 as *mut _));
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,58 +10,60 @@ pub struct Statement<'l> {
|
|||||||
phantom: PhantomData<(&'l raw::sqlite3, raw::sqlite3_stmt)>,
|
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> {
|
pub enum Binding<'l> {
|
||||||
Float(usize, f64),
|
Float(usize, f64),
|
||||||
Integer(usize, i64),
|
Integer(usize, i64),
|
||||||
Text(usize, &'l str),
|
Text(usize, &'l str),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A value stored in a prepared statement.
|
/// A value stored in a result row of a query.
|
||||||
pub trait Value {
|
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<Self>;
|
fn read(statement: &Statement, i: usize) -> Result<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'l> Statement<'l> {
|
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<()> {
|
pub fn bind(&mut self, bindings: &[Binding]) -> Result<()> {
|
||||||
for binding in bindings.iter() {
|
for binding in bindings.iter() {
|
||||||
match *binding {
|
match *binding {
|
||||||
Binding::Float(i, value) => unsafe {
|
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));
|
success!(raw::sqlite3_bind_double(self.raw, i as c_int, value as c_double));
|
||||||
},
|
},
|
||||||
Binding::Integer(i, value) => unsafe {
|
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,
|
success!(raw::sqlite3_bind_int64(self.raw, i as c_int,
|
||||||
value as raw::sqlite3_int64));
|
value as raw::sqlite3_int64));
|
||||||
},
|
},
|
||||||
Binding::Text(i, value) => unsafe {
|
Binding::Text(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_text(self.raw, i as c_int, str_to_c_str!(value),
|
success!(raw::sqlite3_bind_text(self.raw, i as c_int, str_to_c_str!(value), -1,
|
||||||
-1, None));
|
None));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
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]
|
#[inline]
|
||||||
pub fn column<T: Value>(&self, i: usize) -> Result<T> {
|
pub fn column<T: Value>(&self, i: usize) -> Result<T> {
|
||||||
<T as Value>::read(self, i)
|
<T as Value>::read(self, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Take a step.
|
/// Evaluate the statement.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn step(&mut self) -> ResultCode {
|
pub fn step(&mut self) -> ResultCode {
|
||||||
unsafe { ::result::code_from_raw(raw::sqlite3_step(self.raw)) }
|
unsafe { ::result::code_from_raw(raw::sqlite3_step(self.raw)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset.
|
/// Reset the statement.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn reset(&mut self) -> Result<()> {
|
pub fn reset(&mut self) -> Result<()> {
|
||||||
unsafe { success!(raw::sqlite3_reset(self.raw)) };
|
unsafe { success!(raw::sqlite3_reset(self.raw)) };
|
||||||
|
@ -25,7 +25,7 @@ fn workflow() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let sql = r#"INSERT INTO `users` (id, name, age) VALUES (?, ?, ?);"#;
|
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)]));
|
ok!(statement.bind(&[Integer(1, 1), Text(2, "Alice"), Float(3, 20.99)]));
|
||||||
assert!(statement.step() == ResultCode::Done);
|
assert!(statement.step() == ResultCode::Done);
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ fn workflow() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let sql = r#"SELECT * FROM `users`;"#;
|
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!(statement.step() == ResultCode::Row);
|
||||||
assert!(ok!(statement.column::<i64>(0)) == 1);
|
assert!(ok!(statement.column::<i64>(0)) == 1);
|
||||||
assert!(ok!(statement.column::<String>(1)) == String::from("Alice"));
|
assert!(ok!(statement.column::<String>(1)) == String::from("Alice"));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user