2023-08-18 22:32:04 +00:00
|
|
|
#![allow(non_snake_case)]
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[wasm_bindgen()]
|
2023-09-02 18:15:38 +00:00
|
|
|
pub struct VeilidTableDB {
|
2023-09-04 21:34:49 +00:00
|
|
|
inner_table_db: Option<TableDB>,
|
2023-08-18 22:32:04 +00:00
|
|
|
tableName: String,
|
|
|
|
columnCount: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[wasm_bindgen()]
|
2023-09-02 18:15:38 +00:00
|
|
|
impl VeilidTableDB {
|
2023-09-04 18:04:57 +00:00
|
|
|
/// If the column count is greater than an existing TableDB's column count,
|
|
|
|
/// the database will be upgraded to add the missing columns.
|
2023-08-18 22:32:04 +00:00
|
|
|
#[wasm_bindgen(constructor)]
|
2023-09-04 18:04:57 +00:00
|
|
|
pub fn new(tableName: String, columnCount: u32) -> Self {
|
|
|
|
Self {
|
2023-09-04 21:34:49 +00:00
|
|
|
inner_table_db: None,
|
2023-08-18 22:32:04 +00:00
|
|
|
tableName,
|
|
|
|
columnCount,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-04 18:04:57 +00:00
|
|
|
fn getTableDB(&self) -> APIResult<TableDB> {
|
2023-09-04 21:34:49 +00:00
|
|
|
let Some(table_db) = &self.inner_table_db else {
|
2023-09-18 23:49:57 +00:00
|
|
|
return APIResult::Err(veilid_core::VeilidAPIError::generic(
|
|
|
|
"Unable to getTableDB instance. Ensure you've called openTable().",
|
|
|
|
));
|
2023-09-04 18:04:57 +00:00
|
|
|
};
|
|
|
|
APIResult::Ok(table_db.clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get or create the TableDB database table.
|
|
|
|
/// This is called automatically when performing actions on the TableDB.
|
2023-09-04 21:34:49 +00:00
|
|
|
pub async fn openTable(&mut self) -> APIResult<()> {
|
2023-08-18 22:32:04 +00:00
|
|
|
let veilid_api = get_veilid_api()?;
|
|
|
|
let tstore = veilid_api.table_store()?;
|
|
|
|
let table_db = tstore
|
|
|
|
.open(&self.tableName, self.columnCount)
|
|
|
|
.await
|
|
|
|
.map_err(veilid_core::VeilidAPIError::generic)?;
|
2023-09-04 21:34:49 +00:00
|
|
|
self.inner_table_db = Some(table_db);
|
|
|
|
APIRESULT_UNDEFINED
|
2023-08-18 22:32:04 +00:00
|
|
|
}
|
|
|
|
|
2023-09-04 18:04:57 +00:00
|
|
|
/// Delete this TableDB.
|
|
|
|
pub async fn deleteTable(&mut self) -> APIResult<bool> {
|
2023-09-04 21:34:49 +00:00
|
|
|
self.inner_table_db = None;
|
2023-08-18 22:32:04 +00:00
|
|
|
|
|
|
|
let veilid_api = get_veilid_api()?;
|
|
|
|
let tstore = veilid_api.table_store()?;
|
|
|
|
let deleted = tstore
|
|
|
|
.delete(&self.tableName)
|
|
|
|
.await
|
|
|
|
.map_err(veilid_core::VeilidAPIError::generic)?;
|
|
|
|
APIResult::Ok(deleted)
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn ensureOpen(&mut self) {
|
2023-09-04 21:34:49 +00:00
|
|
|
if self.inner_table_db.is_none() {
|
2023-08-18 22:32:04 +00:00
|
|
|
let _ = self.openTable().await;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-04 18:04:57 +00:00
|
|
|
/// Read a key from a column in the TableDB immediately.
|
2023-09-20 04:46:45 +00:00
|
|
|
pub async fn load(&mut self, columnId: u32, key: Box<[u8]>) -> APIResult<Option<Uint8Array>> {
|
2023-08-18 22:32:04 +00:00
|
|
|
self.ensureOpen().await;
|
2023-09-04 18:04:57 +00:00
|
|
|
let table_db = self.getTableDB()?;
|
2023-08-18 22:32:04 +00:00
|
|
|
|
2023-09-12 12:06:49 +00:00
|
|
|
let out = table_db.load(columnId, &key).await?;
|
2023-09-20 04:46:45 +00:00
|
|
|
let out = out.map(|out| Uint8Array::from(out.as_slice()));
|
2023-08-18 22:32:04 +00:00
|
|
|
APIResult::Ok(out)
|
|
|
|
}
|
|
|
|
|
2023-09-04 18:04:57 +00:00
|
|
|
/// Store a key with a value in a column in the TableDB.
|
|
|
|
/// Performs a single transaction immediately.
|
2023-09-20 04:46:45 +00:00
|
|
|
pub async fn store(
|
|
|
|
&mut self,
|
|
|
|
columnId: u32,
|
|
|
|
key: Box<[u8]>,
|
|
|
|
value: Box<[u8]>,
|
|
|
|
) -> APIResult<()> {
|
2023-08-18 22:32:04 +00:00
|
|
|
self.ensureOpen().await;
|
2023-09-04 18:04:57 +00:00
|
|
|
let table_db = self.getTableDB()?;
|
2023-08-18 22:32:04 +00:00
|
|
|
|
2023-09-04 18:04:57 +00:00
|
|
|
table_db.store(columnId, &key, &value).await?;
|
2023-08-18 22:32:04 +00:00
|
|
|
APIRESULT_UNDEFINED
|
|
|
|
}
|
|
|
|
|
2023-09-04 18:04:57 +00:00
|
|
|
/// Delete key with from a column in the TableDB.
|
2023-09-20 04:46:45 +00:00
|
|
|
pub async fn delete(&mut self, columnId: u32, key: Box<[u8]>) -> APIResult<Option<Uint8Array>> {
|
2023-08-18 22:32:04 +00:00
|
|
|
self.ensureOpen().await;
|
2023-09-04 18:04:57 +00:00
|
|
|
let table_db = self.getTableDB()?;
|
2023-08-18 22:32:04 +00:00
|
|
|
|
2023-09-12 12:06:49 +00:00
|
|
|
let out = table_db.delete(columnId, &key).await?;
|
2023-09-20 04:46:45 +00:00
|
|
|
let out = out.map(|out| Uint8Array::from(out.as_slice()));
|
2023-08-18 22:32:04 +00:00
|
|
|
APIResult::Ok(out)
|
|
|
|
}
|
|
|
|
|
2023-09-04 18:04:57 +00:00
|
|
|
/// Get the list of keys in a column of the TableDB.
|
|
|
|
///
|
2023-09-20 04:46:45 +00:00
|
|
|
/// Returns an array of Uint8Array keys.
|
|
|
|
pub async fn getKeys(&mut self, columnId: u32) -> APIResult<Uint8ArrayArray> {
|
2023-08-18 22:32:04 +00:00
|
|
|
self.ensureOpen().await;
|
2023-09-04 18:04:57 +00:00
|
|
|
let table_db = self.getTableDB()?;
|
2023-08-18 22:32:04 +00:00
|
|
|
|
|
|
|
let keys = table_db.clone().get_keys(columnId).await?;
|
2023-09-20 04:46:45 +00:00
|
|
|
let out: Vec<Uint8Array> = keys
|
|
|
|
.into_iter()
|
|
|
|
.map(|k| Uint8Array::from(k.as_slice()))
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
let out = into_unchecked_uint8array_array(out);
|
2023-08-18 22:32:04 +00:00
|
|
|
|
|
|
|
APIResult::Ok(out)
|
|
|
|
}
|
|
|
|
|
2023-09-04 18:04:57 +00:00
|
|
|
/// Start a TableDB write transaction.
|
|
|
|
/// The transaction object must be committed or rolled back before dropping.
|
|
|
|
pub async fn createTransaction(&mut self) -> APIResult<VeilidTableDBTransaction> {
|
2023-08-18 22:32:04 +00:00
|
|
|
self.ensureOpen().await;
|
2023-09-04 18:04:57 +00:00
|
|
|
let table_db = self.getTableDB()?;
|
2023-08-18 22:32:04 +00:00
|
|
|
|
2023-09-04 18:04:57 +00:00
|
|
|
let transaction = table_db.transact();
|
2023-09-04 21:34:49 +00:00
|
|
|
APIResult::Ok(VeilidTableDBTransaction {
|
|
|
|
inner_transaction: Some(transaction),
|
|
|
|
})
|
2023-09-04 18:04:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
|
|
|
pub struct VeilidTableDBTransaction {
|
2023-09-04 21:34:49 +00:00
|
|
|
inner_transaction: Option<TableDBTransaction>,
|
2023-09-04 18:04:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
|
|
|
impl VeilidTableDBTransaction {
|
|
|
|
/// Don't use this constructor directly.
|
|
|
|
/// Use `.createTransaction()` on an instance of `VeilidTableDB` instead.
|
|
|
|
/// @deprecated
|
|
|
|
#[wasm_bindgen(constructor)]
|
2023-09-04 21:34:49 +00:00
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
inner_transaction: None,
|
|
|
|
}
|
2023-09-04 18:04:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn getTransaction(&self) -> APIResult<TableDBTransaction> {
|
2023-09-04 21:34:49 +00:00
|
|
|
let Some(transaction) = &self.inner_transaction else {
|
2023-09-18 23:49:57 +00:00
|
|
|
return APIResult::Err(veilid_core::VeilidAPIError::generic(
|
|
|
|
"Unable to getTransaction instance. inner_transaction is None.",
|
|
|
|
));
|
2023-08-18 22:32:04 +00:00
|
|
|
};
|
2023-09-04 18:04:57 +00:00
|
|
|
APIResult::Ok(transaction.clone())
|
2023-08-18 22:32:04 +00:00
|
|
|
}
|
|
|
|
|
2023-09-04 18:04:57 +00:00
|
|
|
/// Commit the transaction. Performs all actions atomically.
|
|
|
|
pub async fn commit(&self) -> APIResult<()> {
|
|
|
|
let transaction = self.getTransaction()?;
|
|
|
|
transaction.commit().await
|
|
|
|
}
|
2023-08-18 22:32:04 +00:00
|
|
|
|
2023-09-04 18:04:57 +00:00
|
|
|
/// Rollback the transaction. Does nothing to the TableDB.
|
|
|
|
pub fn rollback(&self) -> APIResult<()> {
|
|
|
|
let transaction = self.getTransaction()?;
|
|
|
|
transaction.rollback();
|
|
|
|
APIRESULT_UNDEFINED
|
|
|
|
}
|
2023-08-18 22:32:04 +00:00
|
|
|
|
2023-09-04 18:04:57 +00:00
|
|
|
/// Store a key with a value in a column in the TableDB.
|
|
|
|
/// Does not modify TableDB until `.commit()` is called.
|
2023-09-20 04:46:45 +00:00
|
|
|
pub fn store(&self, col: u32, key: Box<[u8]>, value: Box<[u8]>) -> APIResult<()> {
|
2023-09-04 18:04:57 +00:00
|
|
|
let transaction = self.getTransaction()?;
|
|
|
|
transaction.store(col, &key, &value)
|
|
|
|
}
|
2023-08-18 22:32:04 +00:00
|
|
|
|
2023-09-04 18:04:57 +00:00
|
|
|
/// Delete key with from a column in the TableDB
|
2023-09-20 04:46:45 +00:00
|
|
|
pub fn deleteKey(&self, col: u32, key: Box<[u8]>) -> APIResult<()> {
|
2023-09-04 18:04:57 +00:00
|
|
|
let transaction = self.getTransaction()?;
|
|
|
|
transaction.delete(col, &key)
|
|
|
|
}
|
2023-08-18 22:32:04 +00:00
|
|
|
}
|
2023-09-18 23:49:57 +00:00
|
|
|
|
|
|
|
impl Default for VeilidTableDBTransaction {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::new()
|
|
|
|
}
|
|
|
|
}
|