Skip to content

Commit

Permalink
Merge pull request #284 from libsql/lucio/params-try-into
Browse files Browse the repository at this point in the history
libsql/core: Switch to TryInto for params
  • Loading branch information
penberg authored Aug 15, 2023
2 parents ea165be + 8c2b92f commit c0660de
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 12 deletions.
14 changes: 10 additions & 4 deletions crates/core/src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,13 @@ impl Connection {
pub fn query<S, P>(&self, sql: S, params: P) -> Result<Option<Rows>>
where
S: Into<String>,
P: Into<Params>,
P: TryInto<Params>,
P::Error: Into<crate::BoxError>,
{
let stmt = Statement::prepare(self.clone(), self.raw, sql.into().as_str())?;
let params = params.into();
let params = params
.try_into()
.map_err(|e| Error::ToSqlConversionFailure(e.into()))?;
let ret = stmt.query(&params)?;
Ok(Some(ret))
}
Expand Down Expand Up @@ -134,10 +137,13 @@ impl Connection {
pub fn execute<S, P>(&self, sql: S, params: P) -> Result<u64>
where
S: Into<String>,
P: Into<Params>,
P: TryInto<Params>,
P::Error: Into<crate::BoxError>,
{
let stmt = Statement::prepare(self.clone(), self.raw, sql.into().as_str())?;
let params = params.into();
let params = params
.try_into()
.map_err(|e| Error::ToSqlConversionFailure(e.into()))?;
stmt.execute(&params)
}

Expand Down
2 changes: 2 additions & 0 deletions crates/core/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pub enum Error {
QueryReturnedNoRows,
#[error("Execute returned rows")]
ExecuteReturnedRows,
#[error("unable to convert to sql: `{0}`")]
ToSqlConversionFailure(crate::BoxError),
}

pub(crate) fn error_from_handle(raw: *mut libsql_sys::ffi::sqlite3) -> String {
Expand Down
10 changes: 8 additions & 2 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub mod statement;
pub mod transaction;

pub type Result<T> = std::result::Result<T, errors::Error>;
type BoxError = Box<dyn std::error::Error + Send + Sync>;

pub use libsql_sys::ffi;
pub use libsql_sys::ValueType;
Expand All @@ -75,5 +76,10 @@ pub fn version_number() -> i32 {

/// Return the version of the underlying SQLite library as a string.
pub fn version() -> &'static str {
unsafe { std::ffi::CStr::from_ptr(ffi::sqlite3_libversion()).to_str().unwrap() }
}
unsafe {
std::ffi::CStr::from_ptr(ffi::sqlite3_libversion())
.to_str()
.unwrap()
}
}

17 changes: 12 additions & 5 deletions crates/core/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::ffi::c_char;

use libsql_sys::ValueType;

use crate::{Error, Result};

pub enum Params {
None,
Positional(Vec<Value>),
Expand Down Expand Up @@ -40,18 +42,23 @@ macro_rules! named_params {
///
/// conn.query(
/// "SELECT * FROM users WHERE id IN (?1, ?2, ?3)",
/// params_from_iter(iter)
/// params_from_iter(iter)?
/// )
/// # }
/// ```
pub fn params_from_iter<I>(iter: I) -> Params
pub fn params_from_iter<I>(iter: I) -> Result<Params>
where
I: IntoIterator,
I::Item: Into<Value>,
I::Item: TryInto<Value>,
<I::Item as TryInto<Value>>::Error: Into<crate::BoxError>,
{
let vec = iter.into_iter().map(Into::into).collect();
let vec = iter
.into_iter()
.map(|i| i.try_into())
.collect::<std::result::Result<Vec<_>, _>>()
.map_err(|e| Error::ToSqlConversionFailure(e.into()))?;

Params::Positional(vec)
Ok(Params::Positional(vec))
}

impl From<()> for Params {
Expand Down
5 changes: 4 additions & 1 deletion crates/core/src/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ impl Statement {
match err as u32 {
crate::ffi::SQLITE_DONE => Ok(self.conn.changes()),
crate::ffi::SQLITE_ROW => Err(Error::ExecuteReturnedRows),
_ => Err(Error::LibError(err, errors::error_from_handle(self.conn.raw))),
_ => Err(Error::LibError(
err,
errors::error_from_handle(self.conn.raw),
)),
}
}

Expand Down
29 changes: 29 additions & 0 deletions crates/core/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,32 @@ fn transaction() {
assert_eq!(row.get::<&str>(1).unwrap(), "Alice");
assert!(rows.next().unwrap().is_none());
}

#[test]
fn custom_params() {
let conn = setup();

enum MyValue {
Text(String),
Int(i64),
}

impl TryInto<libsql::Value> for MyValue {
type Error = std::io::Error;

fn try_into(self) -> Result<libsql::Value, Self::Error> {
match self {
MyValue::Text(s) => Ok(Value::Text(s)),
MyValue::Int(i) => Ok(Value::Integer(i)),
}
}
}

let params = vec![MyValue::Int(2), MyValue::Text("Alice".into())];

conn.execute(
"INSERT INTO users (id, name) VALUES (?1, ?2)",
libsql::params_from_iter(params).unwrap(),
)
.unwrap();
}

0 comments on commit c0660de

Please sign in to comment.