#![allow(dead_code)] #![allow(clippy::type_complexity)]
use crate::error::NetabaseError;
use crate::traits::definition::NetabaseDefinitionTrait;
use crate::traits::model::NetabaseModelTrait;
use std::marker::PhantomData;
#[cfg(feature = "redb")]
use redb::{ReadableDatabase, ReadableTable, ReadableTableMetadata, Value};
#[cfg(feature = "redb")]
use std::cell::RefCell;
#[cfg(feature = "redb")]
use crate::databases::redb_store::CompositeKey;
pub struct ReadOnly;
pub struct ReadWrite;
pub struct TxnGuard<'db, D, Mode> {
backend: TxnBackend<'db, D>,
_mode: PhantomData<Mode>,
}
#[allow(clippy::large_enum_variant)]
pub(crate) enum TxnBackend<'db, D> {
#[cfg(feature = "sled")]
Sled(SledTxnBackend<'db, D>),
#[cfg(feature = "redb")]
Redb(RedbTxnBackend<'db, D>),
#[cfg(not(any(feature = "sled", feature = "redb")))]
_Phantom(PhantomData<(&'db (), D)>),
}
#[cfg(feature = "sled")]
pub(crate) struct SledTxnBackend<'db, D> {
pub(crate) db: &'db sled::Db,
pub(crate) _phantom: PhantomData<D>,
}
#[cfg(feature = "redb")]
pub(crate) struct RedbTxnBackend<'db, D> {
pub(crate) read_txn: RefCell<Option<redb::ReadTransaction>>,
pub(crate) write_txn: RefCell<Option<redb::WriteTransaction>>,
pub(crate) db: &'db std::sync::Arc<redb::Database>,
pub(crate) _phantom: PhantomData<D>,
}
pub struct TreeView<'txn, D, M, Mode> {
backend: TreeBackend<'txn, D, M>,
_mode: PhantomData<Mode>,
}
pub(crate) enum TreeBackend<'txn, D, M> {
#[cfg(feature = "sled")]
Sled(SledTreeBackend<'txn, D, M>),
#[cfg(feature = "redb")]
Redb(RedbTreeBackend<'txn, D, M>),
#[cfg(not(any(feature = "sled", feature = "redb")))]
_Phantom(PhantomData<(&'txn (), D, M)>),
}
#[cfg(feature = "sled")]
pub(crate) struct SledTreeBackend<'txn, D, M> {
pub(crate) tree: sled::Tree,
pub(crate) secondary_tree: sled::Tree,
pub(crate) _phantom: PhantomData<(&'txn (), D, M)>,
}
#[cfg(feature = "redb")]
pub(crate) struct RedbTreeBackend<'txn, D, M> {
pub(crate) txn_backend: &'txn RedbTxnBackend<'txn, D>,
pub(crate) table_name: &'static str,
pub(crate) secondary_table_name: &'static str,
pub(crate) _phantom: PhantomData<M>,
}
impl<'db, D> TxnGuard<'db, D, ReadOnly>
where
D: NetabaseDefinitionTrait,
{
#[cfg(feature = "sled")]
pub fn read_sled(db: &'db sled::Db) -> Self {
Self {
backend: TxnBackend::Sled(SledTxnBackend {
db,
_phantom: PhantomData,
}),
_mode: PhantomData,
}
}
#[cfg(feature = "redb")]
pub fn read_redb(db: &'db std::sync::Arc<redb::Database>) -> Result<Self, NetabaseError> {
let read_txn = db.begin_read()?;
Ok(Self {
backend: TxnBackend::Redb(RedbTxnBackend {
read_txn: RefCell::new(Some(read_txn)),
write_txn: RefCell::new(None),
db,
_phantom: PhantomData,
}),
_mode: PhantomData,
})
}
}
impl<'db, D> TxnGuard<'db, D, ReadWrite>
where
D: NetabaseDefinitionTrait,
{
#[cfg(feature = "sled")]
pub fn write_sled(db: &'db sled::Db) -> Self {
Self {
backend: TxnBackend::Sled(SledTxnBackend {
db,
_phantom: PhantomData,
}),
_mode: PhantomData,
}
}
#[cfg(feature = "redb")]
pub fn write_redb(db: &'db std::sync::Arc<redb::Database>) -> Result<Self, NetabaseError> {
let write_txn = db.begin_write()?;
Ok(Self {
backend: TxnBackend::Redb(RedbTxnBackend {
read_txn: RefCell::new(None),
write_txn: RefCell::new(Some(write_txn)),
db,
_phantom: PhantomData,
}),
_mode: PhantomData,
})
}
}
impl<'db, D, Mode> TxnGuard<'db, D, Mode>
where
D: NetabaseDefinitionTrait,
{
pub fn open_tree<M>(&mut self) -> TreeView<'_, D, M, Mode>
where
M: NetabaseModelTrait<D>,
{
match &mut self.backend {
#[cfg(feature = "sled")]
TxnBackend::Sled(backend) => {
let tree_name = M::discriminant_name();
let secondary_tree_name = format!("{}_secondary", tree_name);
let tree = backend.db.open_tree(tree_name).unwrap();
let secondary_tree = backend.db.open_tree(&secondary_tree_name).unwrap();
TreeView {
backend: TreeBackend::Sled(SledTreeBackend {
tree,
secondary_tree,
_phantom: PhantomData,
}),
_mode: PhantomData,
}
}
#[cfg(feature = "redb")]
TxnBackend::Redb(backend) => {
let table_name = M::discriminant_name();
let secondary_table_name = format!("{}_secondary", table_name);
TreeView {
backend: TreeBackend::Redb(RedbTreeBackend {
txn_backend: backend,
table_name,
secondary_table_name: Box::leak(secondary_table_name.into_boxed_str()),
_phantom: PhantomData,
}),
_mode: PhantomData,
}
}
#[cfg(not(any(feature = "sled", feature = "redb")))]
TxnBackend::_Phantom(_) => TreeView {
backend: TreeBackend::_Phantom(PhantomData),
_mode: PhantomData,
},
}
}
}
impl<'db, D> TxnGuard<'db, D, ReadWrite>
where
D: NetabaseDefinitionTrait,
{
pub fn commit(self) -> Result<(), NetabaseError> {
match self.backend {
#[cfg(feature = "sled")]
TxnBackend::Sled(_) => {
Ok(())
}
#[cfg(feature = "redb")]
TxnBackend::Redb(backend) => {
if let Some(txn) = backend.write_txn.borrow_mut().take() {
txn.commit()?;
}
Ok(())
}
#[cfg(not(any(feature = "sled", feature = "redb")))]
TxnBackend::_Phantom(_) => Ok(()),
}
}
pub fn rollback(self) -> Result<(), NetabaseError> {
Ok(())
}
}
impl<'txn, D, M, Mode> TreeView<'txn, D, M, Mode>
where
D: NetabaseDefinitionTrait,
M: NetabaseModelTrait<D>,
{
pub fn get(
&self,
key: <M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
) -> Result<Option<M>, NetabaseError> {
match &self.backend {
#[cfg(feature = "sled")]
TreeBackend::Sled(backend) => {
let key_bytes = bincode::encode_to_vec(&key, bincode::config::standard())
.map_err(crate::error::EncodingDecodingError::from)?;
match backend.tree.get(key_bytes)? {
Some(bytes) => {
let (model, _): (M, usize) =
bincode::decode_from_slice(&bytes, bincode::config::standard())
.map_err(crate::error::EncodingDecodingError::from)?;
Ok(Some(model))
}
None => Ok(None),
}
}
#[cfg(feature = "redb")]
TreeBackend::Redb(backend) => {
use redb::ReadableTable;
let table_def: redb::TableDefinition<
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
M,
> = redb::TableDefinition::new(backend.table_name);
if let Some(ref read_txn) = *backend.txn_backend.read_txn.borrow() {
let table = match read_txn.open_table(table_def) {
Ok(table) => table,
Err(redb::TableError::TableDoesNotExist(_)) => return Ok(None),
Err(e) => return Err(NetabaseError::RedbTableError(e)),
};
match table.get(key)? {
Some(model_guard) => {
let value_ref = model_guard.value();
let v_bytes = M::as_bytes(&value_ref);
let model = bincode::decode_from_slice(
v_bytes.as_ref(),
bincode::config::standard(),
)
.map_err(crate::error::EncodingDecodingError::from)?
.0;
Ok(Some(model))
}
None => Ok(None),
}
} else if let Some(ref write_txn) = *backend.txn_backend.write_txn.borrow() {
let table = match write_txn.open_table(table_def) {
Ok(table) => table,
Err(redb::TableError::TableDoesNotExist(_)) => return Ok(None),
Err(e) => return Err(NetabaseError::RedbTableError(e)),
};
match table.get(key)? {
Some(model_guard) => {
let value_ref = model_guard.value();
let v_bytes = M::as_bytes(&value_ref);
let model = bincode::decode_from_slice(
v_bytes.as_ref(),
bincode::config::standard(),
)
.map_err(crate::error::EncodingDecodingError::from)?
.0;
Ok(Some(model))
}
None => Ok(None),
}
} else {
Err(NetabaseError::Storage("No transaction available".into()))
}
}
#[cfg(not(any(feature = "sled", feature = "redb")))]
TreeBackend::_Phantom(_) => Ok(None),
}
}
pub fn get_by_secondary_key(
&self,
secondary_key: <M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::SecondaryKey,
) -> Result<Vec<M>, NetabaseError>
where
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::SecondaryKey: PartialEq,
{
match &self.backend {
#[cfg(feature = "sled")]
TreeBackend::Sled(backend) => {
let mut results = Vec::new();
for item in backend.secondary_tree.iter() {
let (composite_bytes, _) = item?;
let ((sec_key, prim_key), _count): ((<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::SecondaryKey, <M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey), usize) =
bincode::decode_from_slice(&composite_bytes, bincode::config::standard())
.map_err(crate::error::EncodingDecodingError::from)?;
if sec_key == secondary_key {
if let Some(model) = self.get(prim_key)? {
results.push(model);
}
}
}
Ok(results)
}
#[cfg(feature = "redb")]
TreeBackend::Redb(backend) => {
use redb::ReadableTable;
let sec_table_def: redb::TableDefinition<
CompositeKey<
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::SecondaryKey,
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
>,
(),
> = redb::TableDefinition::new(backend.secondary_table_name);
let mut results = Vec::new();
if let Some(ref read_txn) = *backend.txn_backend.read_txn.borrow() {
let sec_table = match read_txn.open_table(sec_table_def) {
Ok(table) => table,
Err(redb::TableError::TableDoesNotExist(_)) => return Ok(Vec::new()),
Err(e) => return Err(NetabaseError::RedbTableError(e)),
};
for item in sec_table.iter()? {
let (composite_key, _) = item?;
let comp: CompositeKey<
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::SecondaryKey,
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
> = composite_key.value();
if comp.secondary == secondary_key
&& let Some(model) = self.get(comp.primary)?
{
results.push(model);
}
}
} else if let Some(ref write_txn) = *backend.txn_backend.write_txn.borrow() {
let sec_table = match write_txn.open_table(sec_table_def) {
Ok(table) => table,
Err(redb::TableError::TableDoesNotExist(_)) => return Ok(Vec::new()),
Err(e) => return Err(NetabaseError::RedbTableError(e)),
};
for item in sec_table.iter()? {
let (composite_key, _) = item?;
let comp = composite_key.value();
if comp.secondary == secondary_key
&& let Some(model) = self.get(comp.primary)?
{
results.push(model);
}
}
} else {
return Err(NetabaseError::Storage("No transaction available".into()));
}
Ok(results)
}
#[cfg(not(any(feature = "sled", feature = "redb")))]
TreeBackend::_Phantom(_) => Ok(Vec::new()),
}
}
pub fn len(&self) -> Result<usize, NetabaseError> {
match &self.backend {
#[cfg(feature = "sled")]
TreeBackend::Sled(backend) => Ok(backend.tree.len()),
#[cfg(feature = "redb")]
TreeBackend::Redb(backend) => {
let table_def: redb::TableDefinition<
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
M,
> = redb::TableDefinition::new(backend.table_name);
if let Some(ref read_txn) = *backend.txn_backend.read_txn.borrow() {
let table = match read_txn.open_table(table_def) {
Ok(table) => table,
Err(redb::TableError::TableDoesNotExist(_)) => return Ok(0),
Err(e) => return Err(NetabaseError::RedbTableError(e)),
};
Ok(table.len()? as usize)
} else if let Some(ref write_txn) = *backend.txn_backend.write_txn.borrow() {
let table = match write_txn.open_table(table_def) {
Ok(table) => table,
Err(redb::TableError::TableDoesNotExist(_)) => return Ok(0),
Err(e) => return Err(NetabaseError::RedbTableError(e)),
};
Ok(table.len()? as usize)
} else {
Err(NetabaseError::Storage("No transaction available".into()))
}
}
#[cfg(not(any(feature = "sled", feature = "redb")))]
TreeBackend::_Phantom(_) => Ok(0),
}
}
pub fn is_empty(&self) -> Result<bool, NetabaseError> {
Ok(self.len()? == 0)
}
pub fn iter(
&self,
) -> Result<
Vec<(
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
M,
)>,
NetabaseError,
> {
match &self.backend {
#[cfg(feature = "sled")]
TreeBackend::Sled(backend) => {
let mut results = Vec::new();
for item in backend.tree.iter() {
let (key_bytes, value_bytes) = item?;
let (key, _): (
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
usize,
) = bincode::decode_from_slice(&key_bytes, bincode::config::standard())
.map_err(crate::error::EncodingDecodingError::from)?;
let (model, _): (M, usize) =
bincode::decode_from_slice(&value_bytes, bincode::config::standard())
.map_err(crate::error::EncodingDecodingError::from)?;
results.push((key, model));
}
Ok(results)
}
#[cfg(feature = "redb")]
TreeBackend::Redb(backend) => {
let table_def: redb::TableDefinition<
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
M,
> = redb::TableDefinition::new(backend.table_name);
let mut results: Vec<(
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
M,
)> = Vec::new();
if let Some(ref read_txn) = *backend.txn_backend.read_txn.borrow() {
let table = match read_txn.open_table(table_def) {
Ok(table) => table,
Err(redb::TableError::TableDoesNotExist(_)) => return Ok(Vec::new()),
Err(e) => return Err(NetabaseError::RedbTableError(e)),
};
for item in table.iter()? {
let (key, value) = item?;
use redb::Value;
let key_ref = key.value();
let value_ref = value.value();
let k_bytes = <M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey::as_bytes(&key_ref);
let v_bytes = M::as_bytes(&value_ref);
let k = bincode::decode_from_slice(
k_bytes.as_ref(),
bincode::config::standard(),
)
.map_err(crate::error::EncodingDecodingError::from)?
.0;
let v = bincode::decode_from_slice(
v_bytes.as_ref(),
bincode::config::standard(),
)
.map_err(crate::error::EncodingDecodingError::from)?
.0;
results.push((k, v));
}
} else if let Some(ref write_txn) = *backend.txn_backend.write_txn.borrow() {
let table = match write_txn.open_table(table_def) {
Ok(table) => table,
Err(redb::TableError::TableDoesNotExist(_)) => return Ok(Vec::new()),
Err(e) => return Err(NetabaseError::RedbTableError(e)),
};
for item in table.iter()? {
let (key, value) = item?;
use redb::Value;
let key_ref = key.value();
let value_ref = value.value();
let k_bytes = <M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey::as_bytes(&key_ref);
let v_bytes = M::as_bytes(&value_ref);
let k = bincode::decode_from_slice(
k_bytes.as_ref(),
bincode::config::standard(),
)
.map_err(crate::error::EncodingDecodingError::from)?
.0;
let v = bincode::decode_from_slice(
v_bytes.as_ref(),
bincode::config::standard(),
)
.map_err(crate::error::EncodingDecodingError::from)?
.0;
results.push((k, v));
}
} else {
return Err(NetabaseError::Storage("No transaction available".into()));
}
Ok(results)
}
#[cfg(not(any(feature = "sled", feature = "redb")))]
TreeBackend::_Phantom(_) => Ok(Vec::new()),
}
}
}
impl<'txn, D, M> TreeView<'txn, D, M, ReadWrite>
where
D: NetabaseDefinitionTrait,
M: NetabaseModelTrait<D>,
{
pub fn put(&mut self, model: M) -> Result<(), NetabaseError> {
let primary_key = model.primary_key();
let secondary_keys = model.secondary_keys();
match &mut self.backend {
#[cfg(feature = "sled")]
TreeBackend::Sled(backend) => {
let key_bytes = bincode::encode_to_vec(&primary_key, bincode::config::standard())
.map_err(crate::error::EncodingDecodingError::from)?;
let value_bytes = bincode::encode_to_vec(&model, bincode::config::standard())
.map_err(crate::error::EncodingDecodingError::from)?;
backend.tree.insert(&key_bytes, value_bytes)?;
if !secondary_keys.is_empty() {
for sec_key in secondary_keys.values() {
let composite_key = (sec_key, primary_key.clone());
let composite_bytes =
bincode::encode_to_vec(&composite_key, bincode::config::standard())
.map_err(crate::error::EncodingDecodingError::from)?;
backend.secondary_tree.insert(&composite_bytes, &[])?;
}
}
Ok(())
}
#[cfg(feature = "redb")]
TreeBackend::Redb(backend) => {
let table_def: redb::TableDefinition<
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
M,
> = redb::TableDefinition::new(backend.table_name);
let sec_table_def: redb::TableDefinition<
CompositeKey<
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::SecondaryKey,
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
>,
(),
> = redb::TableDefinition::new(backend.secondary_table_name);
if let Some(ref write_txn) = *backend.txn_backend.write_txn.borrow() {
{
let mut table = write_txn.open_table(table_def)?;
table.insert(primary_key.clone(), model.clone())?;
if !secondary_keys.is_empty() {
let mut sec_table = write_txn.open_table(sec_table_def)?;
for sec_key in secondary_keys.values() {
let composite_key =
CompositeKey::new(sec_key.clone(), primary_key.clone());
sec_table.insert(composite_key, ())?;
}
}
}
Ok(())
} else {
Err(NetabaseError::Storage(
"No write transaction available".into(),
))
}
}
#[cfg(not(any(feature = "sled", feature = "redb")))]
TreeBackend::_Phantom(_) => Ok(()),
}
}
pub fn remove(
&mut self,
key: <M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
) -> Result<Option<M>, NetabaseError> {
let model = self.get(key.clone())?;
if model.is_none() {
return Ok(None);
}
match &mut self.backend {
#[cfg(feature = "sled")]
TreeBackend::Sled(backend) => {
let key_bytes = bincode::encode_to_vec(&key, bincode::config::standard())
.map_err(crate::error::EncodingDecodingError::from)?;
backend.tree.remove(&key_bytes)?;
if let Some(ref m) = model {
let secondary_keys = m.secondary_keys();
if !secondary_keys.is_empty() {
for sec_key in secondary_keys.values() {
let composite_key = (sec_key, M::Keys::from(key.clone()));
let composite_bytes =
bincode::encode_to_vec(&composite_key, bincode::config::standard())
.map_err(crate::error::EncodingDecodingError::from)?;
backend.secondary_tree.remove(&composite_bytes)?;
}
}
}
Ok(model)
}
#[cfg(feature = "redb")]
TreeBackend::Redb(backend) => {
let table_def: redb::TableDefinition<
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
M,
> = redb::TableDefinition::new(backend.table_name);
let sec_table_def: redb::TableDefinition<
CompositeKey<
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::SecondaryKey,
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
>,
(),
> = redb::TableDefinition::new(backend.secondary_table_name);
if let Some(ref write_txn) = *backend.txn_backend.write_txn.borrow() {
{
let mut table = write_txn.open_table(table_def)?;
table.remove(key.clone())?;
if let Some(ref m) = model {
let secondary_keys = m.secondary_keys();
if !secondary_keys.is_empty() {
let mut sec_table = write_txn.open_table(sec_table_def)?;
for sec_key in secondary_keys.values() {
let composite_key =
CompositeKey::new(sec_key.clone(), key.clone());
sec_table.remove(composite_key)?;
}
}
}
}
Ok(model)
} else {
Err(NetabaseError::Storage(
"No write transaction available".into(),
))
}
}
#[cfg(not(any(feature = "sled", feature = "redb")))]
TreeBackend::_Phantom(_) => Ok(model),
}
}
pub fn clear(&mut self) -> Result<(), NetabaseError> {
match &mut self.backend {
#[cfg(feature = "sled")]
TreeBackend::Sled(backend) => {
backend.tree.clear()?;
backend.secondary_tree.clear()?;
Ok(())
}
#[cfg(feature = "redb")]
TreeBackend::Redb(backend) => {
let table_def: redb::TableDefinition<
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
M,
> = redb::TableDefinition::new(backend.table_name);
let sec_table_def: redb::TableDefinition<
CompositeKey<
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::SecondaryKey,
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
>,
(),
> = redb::TableDefinition::new(backend.secondary_table_name);
if let Some(ref write_txn) = *backend.txn_backend.write_txn.borrow() {
let keys_to_remove: Vec<
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
> = {
let table = write_txn.open_table(table_def)?;
table.iter()?.map(|item| {
let (k, _) = item.unwrap();
let k_ref = k.value();
let k_bytes = <M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey::as_bytes(&k_ref);
bincode::decode_from_slice(k_bytes.as_ref(), bincode::config::standard()).unwrap().0
}).collect()
};
{
let mut table = write_txn.open_table(table_def)?;
for key in keys_to_remove {
table.remove(key)?;
}
}
let composite_keys_to_remove: Vec<CompositeKey<
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::SecondaryKey,
<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
>> = {
let sec_table = write_txn.open_table(sec_table_def)?;
sec_table
.iter()?
.map(|item| {
let (k, _) = item.unwrap();
let k_ref = k.value();
let k_bytes =
CompositeKey::<
<M::Keys as crate::traits::model::NetabaseModelTraitKey<
D,
>>::SecondaryKey,
<M::Keys as crate::traits::model::NetabaseModelTraitKey<
D,
>>::PrimaryKey,
>::as_bytes(&k_ref);
bincode::decode_from_slice(
k_bytes.as_ref(),
bincode::config::standard(),
)
.unwrap()
.0
})
.collect()
};
{
let mut sec_table = write_txn.open_table(sec_table_def)?;
for sec_key in composite_keys_to_remove {
sec_table.remove(sec_key)?;
}
}
Ok(())
} else {
Err(NetabaseError::Storage(
"No write transaction available".into(),
))
}
}
#[cfg(not(any(feature = "sled", feature = "redb")))]
TreeBackend::_Phantom(_) => Ok(()),
}
}
pub fn put_many<I>(&mut self, models: I) -> Result<(), NetabaseError>
where
I: IntoIterator<Item = M>,
{
for model in models {
self.put(model)?;
}
Ok(())
}
pub fn remove_many<I>(&mut self, keys: I) -> Result<Vec<Option<M>>, NetabaseError>
where
I: IntoIterator<
Item = <M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
>,
{
let mut removed = Vec::new();
for key in keys {
removed.push(self.remove(key)?);
}
Ok(removed)
}
}
impl<'txn, D, M, Mode> TreeView<'txn, D, M, Mode>
where
D: NetabaseDefinitionTrait,
M: NetabaseModelTrait<D>,
{
pub fn get_many<I>(&self, keys: I) -> Result<Vec<Option<M>>, NetabaseError>
where
I: IntoIterator<
Item = <M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
>,
{
let mut results = Vec::new();
for key in keys {
results.push(self.get(key)?);
}
Ok(results)
}
}