diff options
Diffstat (limited to 'database/src/kv')
| -rw-r--r-- | database/src/kv/index.rs | 28 | ||||
| -rw-r--r-- | database/src/kv/mod.rs | 10 |
2 files changed, 35 insertions, 3 deletions
diff --git a/database/src/kv/index.rs b/database/src/kv/index.rs index 5ceab1c..2c96b48 100644 --- a/database/src/kv/index.rs +++ b/database/src/kv/index.rs @@ -8,6 +8,7 @@ use crate::{ MultiBehaviour, RowNum, Sort, SortOrder, kv::{ SubtreeNum, + binning::BinningComponent, helpers::{read_counter, write_counter}, index_key::{IndexKey, SortKey}, prefix_iterator::PrefixIterator, @@ -17,6 +18,33 @@ use anyhow::{Result, bail}; use jellyobject::Object; use std::{collections::HashSet, iter::empty}; +pub fn test_index_identical(ik: &IndexKey, before: &Object, after: &Object) -> bool { + let mut identical = true; + for b in &ik.0.0 { + match b { + BinningComponent::Has(path) => { + identical &= path.get_matching_value(before).is_some() + == path.get_matching_value(after).is_some(); + } + BinningComponent::Match(path) => { + identical &= path.get_matching_values(before) == path.get_matching_values(after); + } + } + } + match &ik.1 { + SortKey::None | SortKey::Count | SortKey::Random => (), + SortKey::Value(path, _) => { + identical &= path.get_matching_values(before) == path.get_matching_values(after); + } + SortKey::Text(paths) => { + for p in paths { + identical &= p.get_matching_values(before) == p.get_matching_values(after); + } + } + } + identical +} + pub fn update_index( txn: &mut dyn jellykv::Transaction, is: SubtreeNum, diff --git a/database/src/kv/mod.rs b/database/src/kv/mod.rs index f391d31..0ce4683 100644 --- a/database/src/kv/mod.rs +++ b/database/src/kv/mod.rs @@ -17,7 +17,7 @@ use crate::{ Database, Query, RowNum, Transaction, kv::{ helpers::{read_counter, write_counter}, - index::{iter_index, read_count_index, update_index}, + index::{iter_index, read_count_index, test_index_identical, update_index}, index_key::{IndexKey, SortKey}, merge_iterator::MergeIterator, prefix_iterator::PrefixIterator, @@ -85,12 +85,16 @@ impl Transaction for &mut dyn jellykv::Transaction { } fn update(&mut self, row: RowNum, entry: Box<Object>) -> Result<()> { debug!("update {row}"); + let after = &entry; let before = self.get(row)?.ok_or(anyhow!("row to update missing"))?; - jellykv::Transaction::set(*self, &row_key(row), bytemuck::cast_slice(entry.export()))?; + jellykv::Transaction::set(*self, &row_key(row), bytemuck::cast_slice(after.export()))?; for (is, ik) in list_indices(*self)? { + if test_index_identical(&ik, &before, &after) { + continue; + } update_index(*self, is, &ik, row, &before, true)?; - update_index(*self, is, &ik, row, &entry, false)?; + update_index(*self, is, &ik, row, &after, false)?; } Ok(()) |