Skip to content

Commit

Permalink
feat: sqlite object exec
Browse files Browse the repository at this point in the history
  • Loading branch information
apskhem committed May 9, 2024
1 parent f2352bd commit 3515bcb
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 27 deletions.
39 changes: 33 additions & 6 deletions hermes/bin/src/runtime_extensions/hermes/sqlite/connection/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ impl HostSqlite for HermesRuntimeContext {
&mut self, resource: wasmtime::component::Resource<Sqlite>, sql: String,
) -> wasmtime::Result<Result<wasmtime::component::Resource<Statement>, Errno>> {
let db_ptr: *mut sqlite3 = resource.rep() as *mut _;
let mut stmt: *mut sqlite3_stmt = std::ptr::null_mut();
let mut stmt_ptr: *mut sqlite3_stmt = std::ptr::null_mut();

let sql_cstring = std::ffi::CString::new(sql)
.map_err(|_| wasmtime::Error::msg("Failed to convert SQL string to CString"))?;
Expand All @@ -131,17 +131,17 @@ impl HostSqlite for HermesRuntimeContext {
sql_cstring.as_ptr(),
-1,
0,
&mut stmt,
&mut stmt_ptr,
std::ptr::null_mut(),
)
};

if result != SQLITE_OK {
Ok(Err(result.into()))
} else if stmt.is_null() {
} else if stmt_ptr.is_null() {
Err(wasmtime::Error::msg("Error preparing a database statement"))
} else {
Ok(Ok(wasmtime::component::Resource::new_own(stmt as u32)))
Ok(Ok(wasmtime::component::Resource::new_own(stmt_ptr as u32)))
}
}

Expand All @@ -154,9 +154,36 @@ impl HostSqlite for HermesRuntimeContext {
fn execute(
&mut self, resource: wasmtime::component::Resource<Sqlite>, sql: String,
) -> wasmtime::Result<Result<(), Errno>> {
let _stmt = self.prepare(resource, sql)??;
// prepare stage
let db_ptr: *mut sqlite3 = resource.rep() as *mut _;
let mut stmt_ptr: *mut sqlite3_stmt = std::ptr::null_mut();

todo!()
let sql_cstring = std::ffi::CString::new(sql)
.map_err(|_| wasmtime::Error::msg("Failed to convert SQL string to CString"))?;

let result = unsafe {
sqlite3_prepare_v3(
db_ptr,
sql_cstring.as_ptr(),
-1,
0,
&mut stmt_ptr,
std::ptr::null_mut(),
)
};

if result != SQLITE_OK {
return Ok(Err(result.into()))
}

// step stage
let result = unsafe { sqlite3_step(stmt_ptr) };

if result != SQLITE_DONE {
return Ok(Err(result.into()))
}

Ok(Ok(()))
}

fn drop(&mut self, _rep: wasmtime::component::Resource<Sqlite>) -> wasmtime::Result<()> {
Expand Down
8 changes: 4 additions & 4 deletions hermes/bin/src/runtime_extensions/hermes/sqlite/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl Host for HermesRuntimeContext {
fn open(
&mut self, readonly: bool, memory: bool,
) -> wasmtime::Result<Result<wasmtime::component::Resource<Sqlite>, Errno>> {
let mut db: *mut sqlite3 = std::ptr::null_mut();
let mut db_ptr: *mut sqlite3 = std::ptr::null_mut();
let db_path = if memory {
":memory:"
} else {
Expand All @@ -38,20 +38,20 @@ impl Host for HermesRuntimeContext {
let result = unsafe {
sqlite3_open_v2(
db_path.as_ptr() as *const _,
&mut db,
&mut db_ptr,
flags,
std::ptr::null(),
)
};

if result != SQLITE_OK {
return Ok(Err(result.into()));
} else if db.is_null() {
} else if db_ptr.is_null() {
return Err(wasmtime::Error::msg(
"Error opening a connection to the database",
));
} else {
return Ok(Ok(wasmtime::component::Resource::new_own(db as u32)));
return Ok(Ok(wasmtime::component::Resource::new_own(db_ptr as u32)));
}
}
}
49 changes: 33 additions & 16 deletions hermes/bin/src/runtime_extensions/hermes/sqlite/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use tokio::{
sync::{mpsc, oneshot},
};

use crate::{app::HermesAppName, runtime_extensions::bindings::hermes::sqlite::api::Sqlite};
use crate::{app::HermesAppName, runtime_extensions::bindings::hermes::sqlite::api::{Sqlite, Statement}};

/// Map of app name to resource holder
type State = DashMap<HermesAppName, InternalState>;
Expand All @@ -16,43 +16,60 @@ type State = DashMap<HermesAppName, InternalState>;
static SQLITE_INTERNAL_STATE: Lazy<State> = Lazy::new(DashMap::new);

struct InternalState {

sqlite_object: Sqlite,
sqlite_id: u32,
id_to_statement_map: DashMap<u32, Statement>,
}

impl InternalState {
fn new() -> Self {
Self {

id_to_sqlite_map: DashMap::new(),
id_to_statement_map: DashMap::new()
}
}

fn drop(id: u32) {

fn drop(&mut self, id: u32) -> Option<u32> {
// Check if the resource exists in id_to_resource_map.
if let Some(resource) = self.get_resource_from_id(id) {
// Check if the id exists in resource_to_id_map.
if let Some(associated_id) = self.get_id_from_resource(&resource) {
// The id should be the same.
if associated_id == id {
// Remove the resource from both maps.
if let Some(r) = self.id_to_resource_map.remove(&id) {
self.resource_to_id_map.remove(&WrappedXPrv(r.1));
return Some(associated_id);
}
}
}
}
None
}
}

/// Get the state.
pub(super) fn get_state() -> &'static State {
&SQLITE_INTERNAL_STATE
&SQLITE_INTERNAL_STATE
}

/// Set the state according to the app context.
pub(crate) fn set_state(app_name: HermesAppName) {
SQLITE_INTERNAL_STATE.insert(app_name, InternalState::new());
SQLITE_INTERNAL_STATE.insert(app_name, InternalState::new());
}

/// Get the resource from the state using id if possible.
pub(crate) fn get_resource(app_name: &HermesAppName, id: u32) -> Option<Sqlite> {
if let Some(res_holder) = SQLITE_INTERNAL_STATE.get(app_name) {
return res_holder.get_resource_from_id(id);
}
None
if let Some(internal_state) = SQLITE_INTERNAL_STATE.get(app_name) {
return internal_state.get_resource_from_id(id);
}
None
}

/// Delete the resource from the state using id if possible.
pub(crate) fn delete_resource(app_name: &HermesAppName, id: u32) -> Option<u32> {
if let Some(mut res_holder) = SQLITE_INTERNAL_STATE.get_mut(app_name) {
return res_holder.drop(id);
}
None
}
if let Some(mut res_holder) = SQLITE_INTERNAL_STATE.get_mut(app_name) {
return res_holder.drop(id);
}
None
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl HostStatement for HermesRuntimeContext {

let result = unsafe { sqlite3_step(stmt_ptr) };

if result != SQLITE_OK {
if result != SQLITE_DONE {
Ok(Err(result.into()))
} else {
Ok(Ok(()))
Expand Down

0 comments on commit 3515bcb

Please sign in to comment.