diff options
| author | metamuffin <metamuffin@disroot.org> | 2026-02-06 01:35:44 +0100 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2026-02-06 01:35:44 +0100 |
| commit | c914529348b8aa74a142b12f2a3b7532350d3f04 (patch) | |
| tree | 643f6b9f51835212355f0662d8aa9312896e97c2 /database/src/kv/mod.rs | |
| parent | 17be68281eae0be371be63db4c59d4ecaf2f1ba4 (diff) | |
| download | jellything-c914529348b8aa74a142b12f2a3b7532350d3f04.tar jellything-c914529348b8aa74a142b12f2a3b7532350d3f04.tar.bz2 jellything-c914529348b8aa74a142b12f2a3b7532350d3f04.tar.zst | |
index key serialization
Diffstat (limited to 'database/src/kv/mod.rs')
| -rw-r--r-- | database/src/kv/mod.rs | 296 |
1 files changed, 126 insertions, 170 deletions
diff --git a/database/src/kv/mod.rs b/database/src/kv/mod.rs index b4bd000..9408916 100644 --- a/database/src/kv/mod.rs +++ b/database/src/kv/mod.rs @@ -6,212 +6,168 @@ pub mod binning; pub mod counters; +pub mod index_key; pub mod prefix_iterator; pub mod sort; use crate::{ Database, Query, RowIter, RowNum, Transaction, - kv::{binning::Binning, sort::SortKey}, + kv::counters::{read_counter, write_counter}, }; -use anyhow::Result; +use anyhow::{Result, anyhow}; use jellyobject::ObjectBuffer; -pub type IndexKey = (Binning, SortKey); -pub type TableNum = u32; +pub type SubtreeNum = u32; + +const T_ROW_COUNTER: SubtreeNum = 0; +const T_ROWS: SubtreeNum = 1; +const T_INDEX_COUNTER: SubtreeNum = 2; +const T_INDICES: SubtreeNum = 3; + +const INDEX_TNUM_OFFSET: SubtreeNum = 64; impl<T: jellykv::Store> Database for T { fn transaction(&self, f: &mut dyn FnMut(&mut dyn Transaction) -> Result<()>) -> Result<()> { - todo!() + jellykv::Store::transaction(self, &mut |mut txn| f(&mut txn)) } } -impl<T: jellykv::Transaction> Transaction for T { - fn insert(&self, entry: ObjectBuffer) -> Result<RowNum> { - todo!() - } +impl Transaction for &mut dyn jellykv::Transaction { + fn insert(&mut self, entry: ObjectBuffer) -> Result<RowNum> { + let mut id_counter = read_counter(*self, T_ROW_COUNTER, 0)?; + let row = id_counter; + id_counter += 1; + write_counter(*self, T_ROW_COUNTER, id_counter)?; - fn get(&self, row: RowNum) -> Result<Option<ObjectBuffer>> { - todo!() + jellykv::Transaction::set( + *self, + &row_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) + } + fn remove(&mut self, row: RowNum) -> Result<()> { + let entry = self.get(row)?.ok_or(anyhow!("row did not exist"))?; + let ob = entry.as_object(); + // for index in self.indices.values() { + // index.remove(db, row, ob)?; + // } + jellykv::Transaction::del(*self, &row_key(row)) } + fn update(&mut self, row: RowNum, entry: ObjectBuffer) -> Result<()> { + let before = self.get(row)?.ok_or(anyhow!("row to update missing"))?; + let before = before.as_object(); + let after = entry.as_object(); - fn remove(&self, row: RowNum) -> Result<()> { - todo!() + jellykv::Transaction::set( + *self, + &row_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(()) } - fn update(&self, row: RowNum, entry: ObjectBuffer) -> Result<()> { - todo!() + fn get(&self, row: RowNum) -> Result<Option<ObjectBuffer>> { + Ok(jellykv::Transaction::get(*self, &row_key(row))?.map(ObjectBuffer::from)) } fn query(&self, 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!() } - fn query_single(&self, query: Query) -> Result<Option<RowNum>> { - todo!() + self.query(query)?.next().transpose() } - fn count(&self, query: Query) -> Result<u64> { - todo!() + 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) } } -// 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) -// } -// } +fn row_key(row: RowNum) -> Vec<u8> { + let mut key = Vec::new(); + key.extend(T_ROWS.to_be_bytes()); + key.extend(row.to_be_bytes()); + key +} -// #[cfg(test)] -// mod test { -// use { -// table::Table, -// test_shared::{NAME, new_bob}, -// }; -// use anyhow::Result; -// use jellykv::Database; +#[cfg(test)] +mod test { + use crate::{ + Database, + test_shared::{NAME, new_bob}, + }; + use anyhow::Result; -// #[test] -// pub fn insert_get() -> Result<()> { -// let db = jellykv::memory::new(); -// let table = Table::new(5); + #[test] + pub fn insert_get() -> Result<()> { + let db = jellykv::memory::new(); -// let mut bob_row = 0; -// db.write_transaction(&mut |txn| { -// bob_row = table.insert(txn, new_bob())?; -// Ok(()) -// })?; + let mut bob_row = 0; + db.transaction(&mut |txn| { + bob_row = txn.insert(new_bob())?; + Ok(()) + })?; -// let mut bob = None; -// db.read_transaction(&mut |txn| { -// bob = table.get(txn, bob_row)?; -// Ok(()) -// })?; + let mut bob = None; + db.transaction(&mut |txn| { + bob = txn.get(bob_row)?; + Ok(()) + })?; -// assert_eq!(bob.unwrap().as_object().get(NAME).unwrap(), "Bob"); -// 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); + #[test] + pub fn update() -> Result<()> { + let db = jellykv::memory::new(); -// let mut bob_row = 0; -// let mut bob = None; + 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(()) -// })?; + db.transaction(&mut |txn| { + bob_row = txn.insert(new_bob())?; + Ok(()) + })?; + db.transaction(&mut |txn| { + let better_bob = new_bob().as_object().insert(NAME, "Better Bob"); + txn.update(bob_row, better_bob)?; + Ok(()) + })?; + db.transaction(&mut |txn| { + bob = txn.get(bob_row)?; + Ok(()) + })?; -// assert_eq!(bob.unwrap().as_object().get(NAME).unwrap(), "Better Bob"); -// Ok(()) -// } -// } + assert_eq!(bob.unwrap().as_object().get(NAME).unwrap(), "Better Bob"); + Ok(()) + } +} |