Merge pull request #18 from rrichardson/iter-dup-test

fix for #17 - deleting values from an iter_dup db fails
without.crypto
Myk Melez 6 years ago committed by GitHub
commit 3a7824fba8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/cursor.rs
  2. 70
      src/transaction.rs

@ -80,7 +80,7 @@ pub trait Cursor<'txn> {
/// Iterate over duplicate items in the database starting from the given /// Iterate over duplicate items in the database starting from the given
/// key. Each item will be returned as an iterator of its duplicates. /// key. Each item will be returned as an iterator of its duplicates.
fn iter_dup_from<K>(&mut self, key: &K) -> IterDup<'txn> where K: AsRef<[u8]> { fn iter_dup_from<K>(&mut self, key: K) -> IterDup<'txn> where K: AsRef<[u8]> {
match self.get(Some(key.as_ref()), None, ffi::MDB_SET_RANGE) { match self.get(Some(key.as_ref()), None, ffi::MDB_SET_RANGE) {
Ok(_) | Err(Error::NotFound) => (), Ok(_) | Err(Error::NotFound) => (),
Err(error) => panic!("mdb_cursor_get returned an unexpected error: {}", error), Err(error) => panic!("mdb_cursor_get returned an unexpected error: {}", error),
@ -89,7 +89,7 @@ pub trait Cursor<'txn> {
} }
/// Iterate over the duplicates of the item in the database with the given key. /// Iterate over the duplicates of the item in the database with the given key.
fn iter_dup_of<K>(&mut self, key: &K) -> Iter<'txn> where K: AsRef<[u8]> { fn iter_dup_of<K>(&mut self, key: K) -> Iter<'txn> where K: AsRef<[u8]> {
match self.get(Some(key.as_ref()), None, ffi::MDB_SET) { match self.get(Some(key.as_ref()), None, ffi::MDB_SET) {
Ok(_) | Err(Error::NotFound) => (), Ok(_) | Err(Error::NotFound) => (),
Err(error) => panic!("mdb_cursor_get returned an unexpected error: {}", error), Err(error) => panic!("mdb_cursor_get returned an unexpected error: {}", error),

@ -332,12 +332,22 @@ impl <'env> RwTransaction<'env> {
let data_val: Option<ffi::MDB_val> = let data_val: Option<ffi::MDB_val> =
data.map(|data| ffi::MDB_val { mv_size: data.len() as size_t, data.map(|data| ffi::MDB_val { mv_size: data.len() as size_t,
mv_data: data.as_ptr() as *mut c_void }); mv_data: data.as_ptr() as *mut c_void });
unsafe {
lmdb_result(ffi::mdb_del(self.txn(), if let Some(mut d) = data_val {
database.dbi(), unsafe {
&mut key_val, lmdb_result(ffi::mdb_del(self.txn(),
data_val.map(|mut data_val| &mut data_val as *mut _) database.dbi(),
.unwrap_or(ptr::null_mut()))) &mut key_val,
&mut d))
}
} else {
unsafe {
lmdb_result(ffi::mdb_del(self.txn(),
database.dbi(),
&mut key_val,
ptr::null_mut()))
}
} }
} }
@ -392,6 +402,7 @@ mod test {
use flags::*; use flags::*;
use super::*; use super::*;
use test_utils::*; use test_utils::*;
use cursor::Cursor;
#[test] #[test]
fn test_put_get_del() { fn test_put_get_del() {
@ -415,6 +426,53 @@ mod test {
assert_eq!(txn.get(db, b"key1"), Err(Error::NotFound)); assert_eq!(txn.get(db, b"key1"), Err(Error::NotFound));
} }
#[test]
fn test_put_get_del_multi() {
let dir = TempDir::new("test").unwrap();
let env = Environment::new().open(dir.path()).unwrap();
let db = env.create_db(None, DatabaseFlags::DUP_SORT).unwrap();
let mut txn = env.begin_rw_txn().unwrap();
txn.put(db, b"key1", b"val1", WriteFlags::empty()).unwrap();
txn.put(db, b"key1", b"val2", WriteFlags::empty()).unwrap();
txn.put(db, b"key1", b"val3", WriteFlags::empty()).unwrap();
txn.put(db, b"key2", b"val1", WriteFlags::empty()).unwrap();
txn.put(db, b"key2", b"val2", WriteFlags::empty()).unwrap();
txn.put(db, b"key2", b"val3", WriteFlags::empty()).unwrap();
txn.put(db, b"key3", b"val1", WriteFlags::empty()).unwrap();
txn.put(db, b"key3", b"val2", WriteFlags::empty()).unwrap();
txn.put(db, b"key3", b"val3", WriteFlags::empty()).unwrap();
txn.commit().unwrap();
let txn = env.begin_rw_txn().unwrap();
{
let mut cur = txn.open_ro_cursor(db).unwrap();
let iter = cur.iter_dup_of(b"key1");
let vals = iter.map(|(_,x)| x).collect::<Vec<_>>();
assert_eq!(vals, vec![b"val1", b"val2", b"val3"]);
}
txn.commit().unwrap();
let mut txn = env.begin_rw_txn().unwrap();
txn.del(db, b"key1", Some(b"val2")).unwrap();
txn.del(db, b"key2", None).unwrap();
txn.commit().unwrap();
let txn = env.begin_rw_txn().unwrap();
{
let mut cur = txn.open_ro_cursor(db).unwrap();
let iter = cur.iter_dup_of(b"key1");
let vals = iter.map(|(_,x)| x).collect::<Vec<_>>();
assert_eq!(vals, vec![b"val1", b"val3"]);
let iter = cur.iter_dup_of(b"key2");
assert_eq!(0, iter.count());
}
txn.commit().unwrap();
}
#[test] #[test]
fn test_reserve() { fn test_reserve() {
let dir = TempDir::new("test").unwrap(); let dir = TempDir::new("test").unwrap();

Loading…
Cancel
Save