diff options
| author | metamuffin <metamuffin@disroot.org> | 2026-02-05 20:31:55 +0100 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2026-02-05 20:31:55 +0100 |
| commit | 65ca3f3450d0067668111f6e13cc3089768c9efe (patch) | |
| tree | 89dceed4f711d25ff2763e18a4be7e1a59e79507 /database/src/kv/mod.rs | |
| parent | 1af0468788c0a592a76398206e6c7479384853ec (diff) | |
| download | jellything-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.rs | 217 |
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(()) +// } +// } |