mirror of
https://github.com/fluencelabs/sqlite-wasm-connector
synced 2025-04-25 00:32:14 +00:00
Implement column reading
This commit is contained in:
parent
f7f9af43ed
commit
ae0a12444b
@ -67,21 +67,12 @@ impl<'l> Drop for Database<'l> {
|
|||||||
extern fn execute_callback(callback: *mut c_void, count: c_int, values: *mut *mut c_char,
|
extern fn execute_callback(callback: *mut c_void, count: c_int, values: *mut *mut c_char,
|
||||||
columns: *mut *mut c_char) -> c_int {
|
columns: *mut *mut c_char) -> c_int {
|
||||||
|
|
||||||
macro_rules! c_str_to_string(
|
|
||||||
($string:expr) => (
|
|
||||||
match ::std::str::from_utf8(::std::ffi::CStr::from_ptr($string).to_bytes()) {
|
|
||||||
Ok(string) => String::from(string),
|
|
||||||
Err(_) => return 1,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
);
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut pairs = Vec::with_capacity(count as usize);
|
let mut pairs = Vec::with_capacity(count as usize);
|
||||||
|
|
||||||
for i in 0..(count as isize) {
|
for i in 0..(count as isize) {
|
||||||
let column = c_str_to_string!(*columns.offset(i) as *const _);
|
let column = c_str_to_string!(*columns.offset(i));
|
||||||
let value = c_str_to_string!(*values.offset(i) as *const _);
|
let value = c_str_to_string!(*values.offset(i));
|
||||||
pairs.push((column, value));
|
pairs.push((column, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +98,13 @@ macro_rules! str_to_c_str(
|
|||||||
);
|
);
|
||||||
);
|
);
|
||||||
|
|
||||||
|
macro_rules! c_str_to_string(
|
||||||
|
($cstr:expr) => (
|
||||||
|
String::from_utf8_lossy(::std::ffi::CStr::from_ptr($cstr as *const _).to_bytes())
|
||||||
|
.into_owned()
|
||||||
|
);
|
||||||
|
);
|
||||||
|
|
||||||
mod database;
|
mod database;
|
||||||
mod statement;
|
mod statement;
|
||||||
|
|
||||||
|
@ -17,6 +17,12 @@ pub enum Binding<'l> {
|
|||||||
Text(usize, &'l str),
|
Text(usize, &'l str),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A value stored in a column.
|
||||||
|
pub trait Value {
|
||||||
|
/// Read the value from a prepared statement at a specific position.
|
||||||
|
fn read(statement: &mut Statement, i: usize) -> Result<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
impl<'l> Statement<'l> {
|
impl<'l> Statement<'l> {
|
||||||
/// Assign values to the placeholders.
|
/// Assign values to the placeholders.
|
||||||
pub fn bind(&mut self, bindings: &[Binding]) -> Result<()> {
|
pub fn bind(&mut self, bindings: &[Binding]) -> Result<()> {
|
||||||
@ -38,6 +44,12 @@ impl<'l> Statement<'l> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the value of a column.
|
||||||
|
#[inline]
|
||||||
|
pub fn column<T: Value>(&mut self, i: usize) -> Result<T> {
|
||||||
|
<T as Value>::read(self, i)
|
||||||
|
}
|
||||||
|
|
||||||
/// Take a step.
|
/// Take a step.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn step(&mut self) -> ResultCode {
|
pub fn step(&mut self) -> ResultCode {
|
||||||
@ -59,6 +71,30 @@ impl<'l> Drop for Statement<'l> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Value for f64 {
|
||||||
|
fn read(statement: &mut Statement, i: usize) -> Result<f64> {
|
||||||
|
Ok(unsafe { ::raw::sqlite3_column_double(statement.raw, i as c_int) as f64 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Value for i64 {
|
||||||
|
fn read(statement: &mut Statement, i: usize) -> Result<i64> {
|
||||||
|
Ok(unsafe { ::raw::sqlite3_column_int64(statement.raw, i as c_int) as i64 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Value for String {
|
||||||
|
fn read(statement: &mut Statement, i: usize) -> Result<String> {
|
||||||
|
unsafe {
|
||||||
|
let pointer = ::raw::sqlite3_column_text(statement.raw, i as c_int);
|
||||||
|
if pointer.is_null() {
|
||||||
|
raise!("cannot read a TEXT column");
|
||||||
|
}
|
||||||
|
Ok(c_str_to_string!(pointer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_raw<'l>(raw: *mut raw::sqlite3_stmt) -> Statement<'l> {
|
pub fn from_raw<'l>(raw: *mut raw::sqlite3_stmt) -> Statement<'l> {
|
||||||
Statement { raw: raw, _phantom: PhantomData }
|
Statement { raw: raw, _phantom: PhantomData }
|
||||||
|
14
tests/lib.rs
14
tests/lib.rs
@ -23,11 +23,14 @@ fn workflow() {
|
|||||||
let sql = r#"CREATE TABLE `users` (id INTEGER, name VARCHAR(255), age REAL);"#;
|
let sql = r#"CREATE TABLE `users` (id INTEGER, name VARCHAR(255), age REAL);"#;
|
||||||
ok!(database.execute(sql, None));
|
ok!(database.execute(sql, None));
|
||||||
|
|
||||||
|
{
|
||||||
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.statement(sql));
|
let mut statement = ok!(database.statement(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
let mut done = false;
|
let mut done = false;
|
||||||
let sql = r#"SELECT * FROM `users`;"#;
|
let sql = r#"SELECT * FROM `users`;"#;
|
||||||
ok!(database.execute(sql, Some(&mut |pairs: Vec<(String, String)>| -> bool {
|
ok!(database.execute(sql, Some(&mut |pairs: Vec<(String, String)>| -> bool {
|
||||||
@ -39,6 +42,17 @@ fn workflow() {
|
|||||||
true
|
true
|
||||||
})));
|
})));
|
||||||
assert!(done);
|
assert!(done);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let sql = r#"SELECT * FROM `users`;"#;
|
||||||
|
let mut statement = ok!(database.statement(sql));
|
||||||
|
assert!(statement.step() == ResultCode::Row);
|
||||||
|
assert!(ok!(statement.column::<i64>(0)) == 1);
|
||||||
|
assert!(ok!(statement.column::<String>(1)) == String::from("Alice"));
|
||||||
|
assert!(ok!(statement.column::<f64>(2)) == 20.99);
|
||||||
|
assert!(statement.step() == ResultCode::Done);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup() -> (PathBuf, Directory) {
|
fn setup() -> (PathBuf, Directory) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user