aboutsummaryrefslogtreecommitdiff
path: root/database/src/kv/mod.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2026-02-05 20:31:55 +0100
committermetamuffin <metamuffin@disroot.org>2026-02-05 20:31:55 +0100
commit65ca3f3450d0067668111f6e13cc3089768c9efe (patch)
tree89dceed4f711d25ff2763e18a4be7e1a59e79507 /database/src/kv/mod.rs
parent1af0468788c0a592a76398206e6c7479384853ec (diff)
downloadjellything-65ca3f3450d0067668111f6e13cc3089768c9efe.tar
jellything-65ca3f3450d0067668111f6e13cc3089768c9efe.tar.bz2
jellything-65ca3f3450d0067668111f6e13cc3089768c9efe.tar.zst
remove read/write distinction for kv transactions; traitify database
Diffstat (limited to 'database/src/kv/mod.rs')
-rw-r--r--database/src/kv/mod.rs217
1 files changed, 217 insertions, 0 deletions
diff --git a/database/src/kv/mod.rs b/database/src/kv/mod.rs
new file mode 100644
index 0000000..b4bd000
--- /dev/null
+++ b/database/src/kv/mod.rs
@@ -0,0 +1,217 @@
+/*
+ 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 <metamuffin.org>
+*/
+
+pub mod binning;
+pub mod counters;
+pub mod prefix_iterator;
+pub mod sort;
+
+use crate::{
+ Database, Query, RowIter, RowNum, Transaction,
+ kv::{binning::Binning, sort::SortKey},
+};
+use anyhow::Result;
+use jellyobject::ObjectBuffer;
+
+pub type IndexKey = (Binning, SortKey);
+pub type TableNum = u32;
+
+impl<T: jellykv::Store> Database for T {
+ fn transaction(&self, f: &mut dyn FnMut(&mut dyn Transaction) -> Result<()>) -> Result<()> {
+ todo!()
+ }
+}
+
+impl<T: jellykv::Transaction> Transaction for T {
+ fn insert(&self, entry: ObjectBuffer) -> Result<RowNum> {
+ todo!()
+ }
+
+ fn get(&self, row: RowNum) -> Result<Option<ObjectBuffer>> {
+ todo!()
+ }
+
+ fn remove(&self, row: RowNum) -> Result<()> {
+ todo!()
+ }
+
+ fn update(&self, row: RowNum, entry: ObjectBuffer) -> Result<()> {
+ todo!()
+ }
+
+ fn query(&self, query: Query) -> Result<RowIter> {
+ todo!()
+ }
+
+ fn query_single(&self, query: Query) -> Result<Option<RowNum>> {
+ todo!()
+ }
+
+ fn count(&self, query: Query) -> Result<u64> {
+ todo!()
+ }
+}
+
+// pub struct Table {
+// id: TableNum,
+// pub(crate) counters: HashMap<Binning, TableNum>,
+// pub(crate) indices: HashMap<IndexKey, TableNum>,
+// }
+// impl Table {
+// pub fn new(id: u32) -> Self {
+// Self {
+// id,
+// counters: HashMap::new(),
+// indices: HashMap::new(),
+// }
+// }
+// fn key(&self, row: RowNum) -> Vec<u8> {
+// 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<impl Iterator<Item = Result<RowNum>>> {
+// 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<RowNum> {
+// 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<Option<ObjectBuffer>> {
+// Ok(txn.get(&self.key(row))?.map(ObjectBuffer::from))
+// }
+// pub fn remove(&self, db: &mut dyn WriteTransaction, row: RowNum) -> Result<bool> {
+// 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<RowIter> {
+// // 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<Option<RowNum>> {
+// self.query(txn, query)?.next().transpose()
+// }
+// pub fn count(&self, txn: &dyn ReadTransaction, query: Query) -> Result<u64> {
+// 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 {
+// 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(())
+// }
+// }