adding get_key_value to multi store

main
Niko 2 years ago
parent 8dfc712d67
commit 843291a848
  1. 30
      src/backend/impl_lmdb/cursor.rs
  2. 18
      src/backend/impl_safe/cursor.rs
  3. 4
      src/backend/traits.rs
  4. 20
      src/store/multi.rs
  5. 42
      tests/env-lmdb.rs

@ -19,6 +19,21 @@ pub struct RoCursorImpl<'c>(pub(crate) lmdb::RoCursor<'c>);
impl<'c> BackendRoCursor<'c> for RoCursorImpl<'c> {
type Iter = IterImpl<'c, lmdb::RoCursor<'c>>;
fn get_key_value<K>(self, key: K, value: crate::value::Value) -> bool
where
K: AsRef<[u8]> + 'c,
{
match self.0.get(
Some(key.as_ref()),
Some(&value.to_bytes().unwrap()),
lmdb::MDB_GET_BOTH,
) {
Err(e) => false,
Ok((Some(k), _)) => true,
Ok((None, _)) => true,
}
}
fn into_iter(self) -> Self::Iter {
// We call RoCursor.iter() instead of RoCursor.iter_start() because
// the latter panics when there are no items in the store, whereas the
@ -53,6 +68,21 @@ pub struct RwCursorImpl<'c>(pub(crate) lmdb::RoCursor<'c>);
impl<'c> BackendRoCursor<'c> for RwCursorImpl<'c> {
type Iter = IterImpl<'c, lmdb::RoCursor<'c>>;
fn get_key_value<K>(self, key: K, value: crate::value::Value) -> bool
where
K: AsRef<[u8]> + 'c,
{
match self.0.get(
Some(key.as_ref()),
Some(&value.to_bytes().unwrap()),
lmdb::MDB_GET_BOTH,
) {
Err(e) => false,
Ok((Some(k), _)) => true,
Ok((None, _)) => false,
}
}
fn into_iter(self) -> Self::Iter {
IterImpl::new(self.0, lmdb::RoCursor::iter)
}

@ -18,6 +18,10 @@ pub struct RoCursorImpl<'c>(pub(crate) &'c Snapshot);
impl<'c> BackendRoCursor<'c> for RoCursorImpl<'c> {
type Iter = IterImpl<'c>;
fn get_key_value<K>(self, key: K, value: crate::value::Value) -> bool {
unimplemented!();
}
fn into_iter(self) -> Self::Iter {
IterImpl(Box::new(self.0.iter()))
}
@ -49,6 +53,13 @@ impl<'c> BackendRoCursor<'c> for RoCursorImpl<'c> {
impl<'c> BackendRoCursor<'c> for RoCursorImpl<'c> {
type Iter = IterImpl<'c>;
fn get_key_value<K>(self, key: K, value: crate::value::Value) -> bool
where
K: AsRef<[u8]> + 'c,
{
unimplemented!();
}
fn into_iter(self) -> Self::Iter {
let flattened = self
.0
@ -86,6 +97,13 @@ pub struct RwCursorImpl<'c>(&'c mut Snapshot);
impl<'c> BackendRoCursor<'c> for RwCursorImpl<'c> {
type Iter = IterImpl<'c>;
fn get_key_value<K>(self, key: K, value: crate::value::Value) -> bool
where
K: AsRef<[u8]> + 'c,
{
unimplemented!();
}
fn into_iter(self) -> Self::Iter {
unimplemented!()
}

@ -212,6 +212,10 @@ pub trait BackendRwDupPrevCursorTransaction: BackendRwTransaction {
pub trait BackendRoCursor<'c>: Debug {
type Iter: BackendIter<'c>;
fn get_key_value<K>(self, key: K, value: crate::value::Value) -> bool
where
K: AsRef<[u8]> + 'c;
fn into_iter(self) -> Self::Iter;
fn into_iter_from<K>(self, key: K) -> Self::Iter

@ -85,6 +85,26 @@ where
})
}
/// Provides a cursor to all of the values for the duplicate entries that match this
/// key
pub fn get_key_value<'r, R, I, C, K>(
&self,
reader: &'r R,
k: K,
v: Value,
) -> Result<bool, StoreError>
where
R: Readable<'r, Database = D, RoCursor = C>,
I: BackendIter<'r>,
C: BackendRoCursor<'r, Iter = I>,
K: AsRef<[u8]> + 'r,
{
let cursor = reader.open_ro_cursor(&self.db)?;
let res = cursor.get_key_value(k, v);
Ok(res)
}
/// Provides the first value that matches this key
pub fn get_first<'r, R, K>(&self, reader: &'r R, k: K) -> Result<Option<Value<'r>>, StoreError>
where

@ -1174,6 +1174,48 @@ fn test_set_map_size() {
assert_eq!(k.info().expect("info").map_size(), 2 * DEFAULT_SIZE);
}
#[test]
fn test_multi_get_key_value() {
let root = Builder::new()
.prefix("test_iter")
.tempdir()
.expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
let sk = k.open_multi("sk", StoreOptions::create()).expect("opened");
// An iterator over an empty store returns no values.
{
let reader = k.read().unwrap();
let mut iter = sk.iter_start(&reader).unwrap();
assert!(iter.next().is_none());
}
let mut writer = k.write().expect("writer");
sk.put(&mut writer, "foo", &Value::Blob(b"1234"))
.expect("blob 1234");
writer.commit().expect("committed");
let reader = k.read().unwrap();
let yes = sk
.get_key_value(&reader, "foo", Value::Blob(b"1234"))
.unwrap();
assert!(yes);
let yes = sk
.get_key_value(&reader, "foo", Value::Blob(b"12345"))
.unwrap();
assert!(!yes);
let yes = sk
.get_key_value(&reader, "foo2", Value::Blob(b"1234"))
.unwrap();
assert!(!yes);
}
#[test]
fn test_iter() {
let root = Builder::new()

Loading…
Cancel
Save