Skip to content

Commit

Permalink
Merge pull request #213 from psarna/rawwrappers
Browse files Browse the repository at this point in the history
Move raw::{Statement, Value} to libsql-sys crate
  • Loading branch information
penberg authored Jul 17, 2023
2 parents ff5d73a + c2c58eb commit c6c0b30
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 86 deletions.
2 changes: 1 addition & 1 deletion crates/core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "libsql"
version = "0.1.1"
version = "0.1.2"
edition = "2021"
description = "libSQL library: the main gateway for interacting with the database"
repository = "https://github.com/libsql/libsql"
Expand Down
1 change: 0 additions & 1 deletion crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ pub mod connection;
pub mod database;
pub mod errors;
pub mod params;
pub mod raw;
pub mod rows;
pub mod statement;

Expand Down
16 changes: 8 additions & 8 deletions crates/core/src/params.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::raw;
use libsql_sys::ValueType;

pub enum Params {
None,
Expand Down Expand Up @@ -47,13 +47,13 @@ impl From<&str> for Value {
}
}

impl From<raw::Value> for Value {
fn from(value: raw::Value) -> Value {
impl From<libsql_sys::Value> for Value {
fn from(value: libsql_sys::Value) -> Value {
match value.value_type() {
crate::rows::ValueType::Null => Value::Null,
crate::rows::ValueType::Integer => Value::Integer(value.int().into()),
crate::rows::ValueType::Float => todo!(),
crate::rows::ValueType::Text => {
ValueType::Null => Value::Null,
ValueType::Integer => Value::Integer(value.int().into()),
ValueType::Float => todo!(),
ValueType::Text => {
let v = value.text();
if v.is_null() {
Value::Null
Expand All @@ -63,7 +63,7 @@ impl From<raw::Value> for Value {
Value::Text(v.to_owned())
}
}
crate::rows::ValueType::Blob => todo!(),
ValueType::Blob => todo!(),
}
}
}
34 changes: 7 additions & 27 deletions crates/core/src/rows.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::{errors, raw, Error, Params, Result, Statement, Value};
use crate::{errors, Error, Params, Result, Statement, Value};
use libsql_sys::ValueType;

use std::cell::RefCell;
use std::sync::Arc;

/// Query result rows.
#[derive(Debug)]
pub struct Rows {
pub(crate) stmt: Arc<raw::Statement>,
pub(crate) stmt: Arc<libsql_sys::Statement>,
pub(crate) err: RefCell<Option<i32>>,
}

Expand Down Expand Up @@ -63,7 +64,7 @@ impl futures::Future for RowsFuture {
}

pub struct Row {
pub(crate) stmt: Arc<raw::Statement>,
pub(crate) stmt: Arc<libsql_sys::Statement>,
}

impl Row {
Expand Down Expand Up @@ -97,42 +98,21 @@ impl Row {
}
}

pub enum ValueType {
Integer,
Float,
Blob,
Text,
Null,
}

impl ValueType {
pub(crate) fn from(val_type: i32) -> ValueType {
match val_type as u32 {
libsql_sys::ffi::SQLITE_INTEGER => ValueType::Integer,
libsql_sys::ffi::SQLITE_FLOAT => ValueType::Float,
libsql_sys::ffi::SQLITE_BLOB => ValueType::Blob,
libsql_sys::ffi::SQLITE_TEXT => ValueType::Text,
libsql_sys::ffi::SQLITE_NULL => ValueType::Null,
_ => todo!(),
}
}
}

pub trait FromValue {
fn from_sql(val: raw::Value) -> Result<Self>
fn from_sql(val: libsql_sys::Value) -> Result<Self>
where
Self: Sized;
}

impl FromValue for i32 {
fn from_sql(val: raw::Value) -> Result<Self> {
fn from_sql(val: libsql_sys::Value) -> Result<Self> {
let ret = val.int();
Ok(ret)
}
}

impl FromValue for &str {
fn from_sql(val: raw::Value) -> Result<Self> {
fn from_sql(val: libsql_sys::Value) -> Result<Self> {
let ret = val.text();
if ret.is_null() {
return Err(Error::NullValue);
Expand Down
13 changes: 8 additions & 5 deletions crates/core/src/statement.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
use crate::{errors, raw, Error, Params, Result, Rows, Value};
use crate::{errors, Error, Params, Result, Rows, Value};

use std::cell::RefCell;
use std::sync::{Arc, Mutex};
use std::sync::Arc;

/// A prepared statement.
pub struct Statement {
inner: Arc<raw::Statement>,
inner: Arc<libsql_sys::Statement>,
}

impl Statement {
pub(crate) fn prepare(raw: *mut libsql_sys::ffi::sqlite3, sql: &str) -> Result<Statement> {
match unsafe { raw::prepare_stmt(raw, sql) } {
match unsafe { libsql_sys::prepare_stmt(raw, sql) } {
Ok(stmt) => Ok(Statement {
inner: Arc::new(stmt),
}),
Err(err) => Err(Error::PrepareFailed(
Err(libsql_sys::Error::LibError(err)) => Err(Error::PrepareFailed(
sql.to_string(),
errors::sqlite_code_to_error(err),
)),
Err(err) => Err(Error::Misuse(format!(
"Unexpected error while preparing statement: {err}"
))),
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/libsql-sys/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "libsql-sys"
version = "0.2.8"
version = "0.2.9"
edition = "2021"
license = "MIT"
description = "Native bindings to libSQL"
Expand Down
12 changes: 12 additions & 0 deletions crates/libsql-sys/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,16 @@ impl std::fmt::Display for Error {
}
}

impl From<i32> for Error {
fn from(e: i32) -> Self {
Self::LibError(e as std::ffi::c_int)
}
}

impl From<u32> for Error {
fn from(e: u32) -> Self {
Self::LibError(e as std::ffi::c_int)
}
}

pub type Result<T> = std::result::Result<T, Error>;
4 changes: 4 additions & 0 deletions crates/libsql-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ pub mod ffi {

pub mod connection;
pub mod error;
pub mod statement;
pub mod types;
pub mod value;
pub mod wal_hook;

pub use connection::Connection;
pub use error::{Error, Result};
pub use statement::{prepare_stmt, Statement};
pub use types::*;
pub use value::{Value, ValueType};
pub use wal_hook::{WalHook, WalMethodsHook};
65 changes: 22 additions & 43 deletions crates/core/src/raw.rs → crates/libsql-sys/src/statement.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#![allow(clippy::missing_safety_doc)]

pub type Error = i32;

pub type Result<T> = std::result::Result<T, Error>;
use crate::error::Result;

#[derive(Debug)]
pub struct Statement {
pub(crate) raw_stmt: *mut libsql_sys::ffi::sqlite3_stmt,
pub raw_stmt: *mut crate::ffi::sqlite3_stmt,
}

// Safety: works as long as libSQL is compiled and set up with SERIALIZABLE threading model, which is the default.
Expand All @@ -19,7 +17,7 @@ impl Drop for Statement {
fn drop(&mut self) {
if !self.raw_stmt.is_null() {
unsafe {
libsql_sys::ffi::sqlite3_finalize(self.raw_stmt);
crate::ffi::sqlite3_finalize(self.raw_stmt);
}
}
}
Expand All @@ -28,26 +26,26 @@ impl Drop for Statement {
impl Statement {
pub fn bind_null(&self, idx: i32) {
unsafe {
libsql_sys::ffi::sqlite3_bind_null(self.raw_stmt, idx);
crate::ffi::sqlite3_bind_null(self.raw_stmt, idx);
}
}

pub fn bind_int64(&self, idx: i32, value: i64) {
unsafe {
libsql_sys::ffi::sqlite3_bind_int64(self.raw_stmt, idx, value);
crate::ffi::sqlite3_bind_int64(self.raw_stmt, idx, value);
}
}

pub fn bind_double(&self, idx: i32, value: f64) {
unsafe {
libsql_sys::ffi::sqlite3_bind_double(self.raw_stmt, idx, value);
crate::ffi::sqlite3_bind_double(self.raw_stmt, idx, value);
}
}

pub fn bind_text(&self, idx: i32, value: &str) {
unsafe {
let value = value.as_bytes();
libsql_sys::ffi::sqlite3_bind_text(
crate::ffi::sqlite3_bind_text(
self.raw_stmt,
idx,
value.as_ptr() as *const i8,
Expand All @@ -59,7 +57,7 @@ impl Statement {

pub fn bind_blob(&self, idx: i32, value: &[u8]) {
unsafe {
libsql_sys::ffi::sqlite3_bind_blob(
crate::ffi::sqlite3_bind_blob(
self.raw_stmt,
idx,
value.as_ptr() as *const std::ffi::c_void,
Expand All @@ -69,39 +67,39 @@ impl Statement {
}
}

pub fn step(&self) -> Error {
unsafe { libsql_sys::ffi::sqlite3_step(self.raw_stmt) }
pub fn step(&self) -> std::ffi::c_int {
unsafe { crate::ffi::sqlite3_step(self.raw_stmt) }
}

pub fn reset(&self) -> Error {
unsafe { libsql_sys::ffi::sqlite3_reset(self.raw_stmt) }
pub fn reset(&self) -> std::ffi::c_int {
unsafe { crate::ffi::sqlite3_reset(self.raw_stmt) }
}

pub fn column_count(&self) -> i32 {
unsafe { libsql_sys::ffi::sqlite3_column_count(self.raw_stmt) }
unsafe { crate::ffi::sqlite3_column_count(self.raw_stmt) }
}

pub fn column_value(&self, idx: i32) -> Value {
let raw_value = unsafe { libsql_sys::ffi::sqlite3_column_value(self.raw_stmt, idx) };
Value { raw_value }
pub fn column_value(&self, idx: i32) -> crate::Value {
let raw_value = unsafe { crate::ffi::sqlite3_column_value(self.raw_stmt, idx) };
crate::Value { raw_value }
}

pub fn column_type(&self, idx: i32) -> i32 {
unsafe { libsql_sys::ffi::sqlite3_column_type(self.raw_stmt, idx) }
unsafe { crate::ffi::sqlite3_column_type(self.raw_stmt, idx) }
}

pub fn column_name(&self, idx: i32) -> &str {
let raw_name = unsafe { libsql_sys::ffi::sqlite3_column_name(self.raw_stmt, idx) };
let raw_name = unsafe { crate::ffi::sqlite3_column_name(self.raw_stmt, idx) };
let raw_name = unsafe { std::ffi::CStr::from_ptr(raw_name as *const i8) };
let raw_name = raw_name.to_str().unwrap();
raw_name
}
}

pub unsafe fn prepare_stmt(raw: *mut libsql_sys::ffi::sqlite3, sql: &str) -> Result<Statement> {
pub unsafe fn prepare_stmt(raw: *mut crate::ffi::sqlite3, sql: &str) -> Result<Statement> {
let mut raw_stmt = std::ptr::null_mut();
let err = unsafe {
libsql_sys::ffi::sqlite3_prepare_v2(
crate::ffi::sqlite3_prepare_v2(
raw,
sql.as_ptr() as *const i8,
sql.len() as i32,
Expand All @@ -110,26 +108,7 @@ pub unsafe fn prepare_stmt(raw: *mut libsql_sys::ffi::sqlite3, sql: &str) -> Res
)
};
match err as u32 {
libsql_sys::ffi::SQLITE_OK => Ok(Statement { raw_stmt }),
_ => Err(err),
}
}

pub struct Value {
raw_value: *mut libsql_sys::ffi::sqlite3_value,
}

impl Value {
pub fn value_type(&self) -> crate::rows::ValueType {
let raw_type = unsafe { libsql_sys::ffi::sqlite3_value_type(self.raw_value) };
crate::rows::ValueType::from(raw_type)
}

pub fn int(&self) -> i32 {
unsafe { libsql_sys::ffi::sqlite3_value_int(self.raw_value) }
}

pub fn text(&self) -> *const u8 {
unsafe { libsql_sys::ffi::sqlite3_value_text(self.raw_value) }
crate::ffi::SQLITE_OK => Ok(Statement { raw_stmt }),
_ => Err(err.into()),
}
}
41 changes: 41 additions & 0 deletions crates/libsql-sys/src/value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#![allow(clippy::missing_safety_doc)]

pub enum ValueType {
Integer,
Float,
Blob,
Text,
Null,
}

impl ValueType {
pub fn from(val_type: i32) -> ValueType {
match val_type as u32 {
crate::ffi::SQLITE_INTEGER => ValueType::Integer,
crate::ffi::SQLITE_FLOAT => ValueType::Float,
crate::ffi::SQLITE_BLOB => ValueType::Blob,
crate::ffi::SQLITE_TEXT => ValueType::Text,
crate::ffi::SQLITE_NULL => ValueType::Null,
_ => todo!(),
}
}
}

pub struct Value {
pub raw_value: *mut crate::ffi::sqlite3_value,
}

impl Value {
pub fn value_type(&self) -> ValueType {
let raw_type = unsafe { crate::ffi::sqlite3_value_type(self.raw_value) };
ValueType::from(raw_type)
}

pub fn int(&self) -> i32 {
unsafe { crate::ffi::sqlite3_value_int(self.raw_value) }
}

pub fn text(&self) -> *const u8 {
unsafe { crate::ffi::sqlite3_value_text(self.raw_value) }
}
}

0 comments on commit c6c0b30

Please sign in to comment.