diff --git a/src/sqlite.rs b/src/sqlite.rs index b896a4d..2f8c336 100644 --- a/src/sqlite.rs +++ b/src/sqlite.rs @@ -1,7 +1,7 @@ +use std::collections::HashMap; use serde::{Deserialize, Serialize}; use thiserror::Error; -use crate::package_id::PackageId; - +use crate::{PackageId, Request, Message, get_payload}; #[derive(Debug, Serialize, Deserialize)] pub struct SqliteRequest { @@ -70,3 +70,162 @@ pub enum SqliteError { #[error("sqlite: input bytes/json/key error: {error}")] InputError { error: String }, } + +pub fn new( + package_id: PackageId, + db: String, +) -> anyhow::Result<()> { + let res = Request::new() + .target(("our", "sqlite", "sys", "uqbar")) + .ipc(serde_json::to_vec(&SqliteRequest { + package_id, + db, + action: SqliteAction::New, + })?) + .send_and_await_response(5)?; + + match res { + Ok(Message::Response { ipc, .. }) => { + let resp = serde_json::from_slice::(&ipc).map_err(|e| SqliteError::InputError { + error: format!("sqlite: gave unparsable response: {}", e), + })?; + + if let SqliteResponse::Ok = resp { + Ok(()) + } else { + Err(anyhow::anyhow!("sqlite: unexpected response: {:?}", resp)) + } + }, + _ => return Err(anyhow::anyhow!("sqlite: unexpected response")), + } +} + +pub fn read( + package_id: PackageId, + db: String, + query: String, + params: Vec, +) -> anyhow::Result>> { + let res = Request::new() + .target(("our", "sqlite", "sys", "uqbar")) + .ipc(serde_json::to_vec(&SqliteRequest { + package_id, + db, + action: SqliteAction::Read { query }, + })?) + .payload_bytes(serde_json::to_vec(¶ms)?) + .send_and_await_response(5)?; + + match res { + Ok(Message::Response { ipc, .. }) => { + let resp = serde_json::from_slice::(&ipc).map_err(|e| SqliteError::InputError { + error: format!("sqlite: gave unparsable response: {}", e), + })?; + + if let SqliteResponse::Read = resp { + let payload = get_payload().ok_or_else(|| SqliteError::InputError { + error: format!("sqlite: no payload"), + })?; + let values = serde_json::from_slice::>>(&payload.bytes).map_err(|e| SqliteError::InputError { + error: format!("sqlite: gave unparsable response: {}", e), + })?; + Ok(values) + } else { + Err(anyhow::anyhow!("sqlite: unexpected response: {:?}", resp)) + } + }, + _ => return Err(anyhow::anyhow!("sqlite: unexpected response")), + } +} + +pub fn write( + package_id: PackageId, + db: String, + statement: String, + params: Vec, + tx_id: Option, +) -> anyhow::Result<()> { + let res = Request::new() + .target(("our", "sqlite", "sys", "uqbar")) + .ipc(serde_json::to_vec(&SqliteRequest { + package_id, + db, + action: SqliteAction::Write { statement, tx_id }, + })?) + .payload_bytes(serde_json::to_vec(¶ms)?) + .send_and_await_response(5)?; + + match res { + Ok(Message::Response { ipc, .. }) => { + let resp = serde_json::from_slice::(&ipc).map_err(|e| SqliteError::InputError { + error: format!("sqlite: gave unparsable response: {}", e), + })?; + + if let SqliteResponse::Ok = resp { + Ok(()) + } else { + Err(anyhow::anyhow!("sqlite: unexpected response: {:?}", resp)) + } + }, + _ => return Err(anyhow::anyhow!("sqlite: unexpected response")), + } +} + +pub fn begin_tx( + package_id: PackageId, + db: String, +) -> anyhow::Result { + let res = Request::new() + .target(("our", "sqlite", "sys", "uqbar")) + .ipc(serde_json::to_vec(&SqliteRequest { + package_id, + db, + action: SqliteAction::BeginTx, + })?) + .send_and_await_response(5)?; + + match res { + Ok(Message::Response { ipc, .. }) => { + let resp = serde_json::from_slice::(&ipc).map_err(|e| SqliteError::InputError { + error: format!("sqlite: gave unparsable response: {}", e), + })?; + + if let SqliteResponse::BeginTx { tx_id } = resp { + Ok(tx_id) + } else { + Err(anyhow::anyhow!("sqlite: unexpected response: {:?}", resp)) + } + }, + _ => return Err(anyhow::anyhow!("sqlite: unexpected response")), + } +} + +pub fn commit_tx( + package_id: PackageId, + db: String, + tx_id: u64, +) -> anyhow::Result<()> { + let res = Request::new() + .target(("our", "sqlite", "sys", "uqbar")) + .ipc(serde_json::to_vec(&SqliteRequest { + package_id, + db, + action: SqliteAction::Commit { tx_id }, + })?) + .send_and_await_response(5)?; + + match res { + Ok(Message::Response { ipc, .. }) => { + let resp = serde_json::from_slice::(&ipc).map_err(|e| SqliteError::InputError { + error: format!("sqlite: gave unparsable response: {}", e), + })?; + + if let SqliteResponse::Ok = resp { + Ok(()) + } else { + Err(anyhow::anyhow!("sqlite: unexpected response: {:?}", resp)) + } + }, + _ => return Err(anyhow::anyhow!("sqlite: unexpected response")), + } +} \ No newline at end of file