From 65ca3f3450d0067668111f6e13cc3089768c9efe Mon Sep 17 00:00:00 2001 From: metamuffin Date: Thu, 5 Feb 2026 20:31:55 +0100 Subject: remove read/write distinction for kv transactions; traitify database --- database/src/table.rs | 184 -------------------------------------------------- 1 file changed, 184 deletions(-) delete mode 100644 database/src/table.rs (limited to 'database/src/table.rs') diff --git a/database/src/table.rs b/database/src/table.rs deleted file mode 100644 index ee8d66b..0000000 --- a/database/src/table.rs +++ /dev/null @@ -1,184 +0,0 @@ -/* - This file is part of jellything (https://codeberg.org/metamuffin/jellything) - which is licensed under the GNU Affero General Public License (version 3); see /COPYING. - Copyright (C) 2026 metamuffin -*/ - -use crate::{ - counters::{read_counter, write_counter}, - filter::binning::Binning, - prefix_iterator::PrefixIterator, - query::Query, - sort::{Index, SortKey}, -}; -use anyhow::{Result, anyhow}; -use jellykv::{ReadTransaction, WriteTransaction}; -use jellyobject::ObjectBuffer; -use std::collections::HashMap; - -pub type TableNum = u32; -pub type RowNum = u64; - -pub type RowIter = Box>>; -pub type IndexKey = (Binning, SortKey); - -pub struct Table { - id: TableNum, - pub(crate) counters: HashMap, - pub(crate) indices: HashMap, -} -impl Table { - pub fn new(id: u32) -> Self { - Self { - id, - counters: HashMap::new(), - indices: HashMap::new(), - } - } - fn key(&self, row: RowNum) -> Vec { - let mut key = Vec::new(); - key.extend(self.id.to_be_bytes()); - key.extend(row.to_be_bytes()); - key - } - pub fn iter(&self, txn: &dyn ReadTransaction) -> Result>> { - Ok(PrefixIterator { - inner: txn.iter(&self.id.to_be_bytes(), false)?, - prefix: self.id.to_be_bytes().to_vec().into(), - } - .map(|r| r.map(|r| RowNum::from_be_bytes(r.try_into().unwrap())))) - } - pub fn insert(&self, txn: &mut dyn WriteTransaction, entry: ObjectBuffer) -> Result { - let mut id_counter = read_counter(txn, self.id)?; - let row = id_counter; - id_counter += 1; - write_counter(txn, self.id, id_counter)?; - - txn.set(&self.key(row), bytemuck::cast_slice(entry.0.as_slice()))?; - - let ob = entry.as_object(); - for idx in self.indices.values() { - idx.add(txn, row, ob)?; - } - - Ok(row) - } - pub fn get(&self, txn: &dyn ReadTransaction, row: RowNum) -> Result> { - Ok(txn.get(&self.key(row))?.map(ObjectBuffer::from)) - } - pub fn remove(&self, db: &mut dyn WriteTransaction, row: RowNum) -> Result { - let Some(entry) = self.get(db, row)? else { - return Ok(false); - }; - let ob = entry.as_object(); - for index in self.indices.values() { - index.remove(db, row, ob)?; - } - db.del(&self.key(row))?; - Ok(true) - } - pub fn update( - &self, - txn: &mut dyn WriteTransaction, - row: RowNum, - entry: ObjectBuffer, - ) -> Result<()> { - let before = self - .get(txn, row)? - .ok_or(anyhow!("row to update missing"))?; - let before = before.as_object(); - let after = entry.as_object(); - - txn.set(&self.key(row), bytemuck::cast_slice(entry.0.as_slice()))?; - - for index in self.indices.values() { - if !index.compare(before, after) { - index.remove(txn, row, before)?; - index.add(txn, row, after)?; - } - } - - Ok(()) - } - pub fn query(&self, txn: &dyn ReadTransaction, query: Query) -> Result { - // query - // .filter - // .get_bins() - // .into_iter() - // .flat_map(|b| { - // let ikey = (b, query.sort.key()); - // self.indices.get(&ikey) - // }) - // .map(|i| i.query(txn, &query.sort)) - todo!() - } - pub fn query_single(&self, txn: &dyn ReadTransaction, query: Query) -> Result> { - self.query(txn, query)?.next().transpose() - } - pub fn count(&self, txn: &dyn ReadTransaction, query: Query) -> Result { - let mut total = 0; - for b in query.filter.get_bins() { - if let Some(&c) = self.counters.get(&b) { - total += read_counter(txn, c)?; - } - } - Ok(total) - } -} - -#[cfg(test)] -mod test { - use crate::{ - table::Table, - test_shared::{NAME, new_bob}, - }; - use anyhow::Result; - use jellykv::Database; - - #[test] - pub fn insert_get() -> Result<()> { - let db = jellykv::memory::new(); - let table = Table::new(5); - - let mut bob_row = 0; - db.write_transaction(&mut |txn| { - bob_row = table.insert(txn, new_bob())?; - Ok(()) - })?; - - let mut bob = None; - db.read_transaction(&mut |txn| { - bob = table.get(txn, bob_row)?; - Ok(()) - })?; - - assert_eq!(bob.unwrap().as_object().get(NAME).unwrap(), "Bob"); - Ok(()) - } - - #[test] - pub fn update() -> Result<()> { - let db = jellykv::memory::new(); - let table = Table::new(5); - - let mut bob_row = 0; - let mut bob = None; - - db.write_transaction(&mut |txn| { - bob_row = table.insert(txn, new_bob())?; - Ok(()) - })?; - db.write_transaction(&mut |txn| { - let better_bob = new_bob().as_object().insert(NAME, "Better Bob"); - table.update(txn, bob_row, better_bob)?; - Ok(()) - })?; - db.read_transaction(&mut |txn| { - bob = table.get(txn, bob_row)?; - Ok(()) - })?; - - assert_eq!(bob.unwrap().as_object().get(NAME).unwrap(), "Better Bob"); - Ok(()) - } -} -- cgit v1.3