From a5200104dcc5ffdbe400a2ae660ce4f9a9573976 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 10 Jul 2016 15:27:22 -0700 Subject: [PATCH 1/4] Have iter_from/iter_dup_from return a Result It previously called unwrap() which panics if a key isn't found --- src/cursor.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cursor.rs b/src/cursor.rs index 7bc8ce4..c39f732 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -61,9 +61,9 @@ pub trait Cursor<'txn> { /// For databases with duplicate data items (`DatabaseFlags::DUP_SORT`), the /// duplicate data items of each key will be returned before moving on to /// the next key. - fn iter_from(&mut self, key: K) -> Iter<'txn> where K: AsRef<[u8]> { - self.get(Some(key.as_ref()), None, ffi::MDB_SET_RANGE).unwrap(); - Iter::new(self.cursor(), ffi::MDB_GET_CURRENT, ffi::MDB_NEXT) + fn iter_from(&mut self, key: K) -> Result> where K: AsRef<[u8]> { + try!(self.get(Some(key.as_ref()), None, ffi::MDB_SET_RANGE)); + Ok(Iter::new(self.cursor(), ffi::MDB_GET_CURRENT, ffi::MDB_NEXT)) } /// Iterate over duplicate database items. The iterator will begin with the @@ -82,9 +82,9 @@ pub trait Cursor<'txn> { /// Iterate over duplicate items in the database starting from the given /// key. Each item will be returned as an iterator of its duplicates. - fn iter_dup_from(&mut self, key: &K) -> IterDup<'txn> where K: AsRef<[u8]> { - self.get(Some(key.as_ref()), None, ffi::MDB_SET_RANGE).unwrap(); - IterDup::new(self.cursor(), ffi::MDB_GET_CURRENT) + fn iter_dup_from(&mut self, key: &K) -> Result> where K: AsRef<[u8]> { + try!(self.get(Some(key.as_ref()), None, ffi::MDB_SET_RANGE)); + Ok(IterDup::new(self.cursor(), ffi::MDB_GET_CURRENT)) } /// Iterate over the duplicates of the item in the database with the given @@ -419,7 +419,7 @@ mod test { assert_eq!(items, cursor.iter_start().collect::>()); assert_eq!(items.clone().into_iter().skip(1).collect::>(), - cursor.iter_from(b"key2").collect::>()); + cursor.iter_from(b"key2").unwrap().collect::>()); } #[test] @@ -458,10 +458,10 @@ mod test { cursor.iter_dup_start().flat_map(|x| x).collect::>()); assert_eq!(items.clone().into_iter().skip(3).collect::>(), - cursor.iter_dup_from(b"b").flat_map(|x| x).collect::>()); + cursor.iter_dup_from(b"b").unwrap().flat_map(|x| x).collect::>()); assert_eq!(items.clone().into_iter().skip(3).collect::>(), - cursor.iter_dup_from(b"ab").flat_map(|x| x).collect::>()); + cursor.iter_dup_from(b"ab").unwrap().flat_map(|x| x).collect::>()); assert_eq!(items.clone().into_iter().skip(3).take(3).collect::>(), cursor.iter_dup_of(b"b").unwrap().collect::>()); From 53fd6afdb6a88ef81fe03fcce07bb3ec9ecff5b9 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 10 Jul 2016 16:01:36 -0700 Subject: [PATCH 2/4] Test iter_from/iter_dup_from with nonexistent keys --- src/cursor.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cursor.rs b/src/cursor.rs index c39f732..0c4daf5 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -420,6 +420,8 @@ mod test { assert_eq!(items.clone().into_iter().skip(1).collect::>(), cursor.iter_from(b"key2").unwrap().collect::>()); + + assert!(cursor.iter_from(b"foo").is_err()); } #[test] @@ -466,6 +468,7 @@ mod test { assert_eq!(items.clone().into_iter().skip(3).take(3).collect::>(), cursor.iter_dup_of(b"b").unwrap().collect::>()); + assert!(cursor.iter_dup_from(b"foo").is_err()); assert!(cursor.iter_dup_of(b"foo").is_err()); } From d6dad15f3ec6ec662822ee87ae586c18a004c744 Mon Sep 17 00:00:00 2001 From: Myk Melez Date: Thu, 24 May 2018 18:28:54 -0700 Subject: [PATCH 3/4] confirm that iter_from/iter_dup_from seek to first key >= specified key --- src/cursor.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/cursor.rs b/src/cursor.rs index 61058bd..11c189a 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -424,7 +424,8 @@ mod test { let items: Vec<(&[u8], &[u8])> = vec!((b"key1", b"val1"), (b"key2", b"val2"), - (b"key3", b"val3")); + (b"key3", b"val3"), + (b"key5", b"val5")); { let mut txn = env.begin_rw_txn().unwrap(); @@ -447,7 +448,10 @@ mod test { assert_eq!(items.clone().into_iter().skip(1).collect::>(), cursor.iter_from(b"key2").unwrap().collect::>()); - assert!(cursor.iter_from(b"foo").is_err()); + assert_eq!(items.clone().into_iter().skip(3).collect::>(), + cursor.iter_from(b"key4").unwrap().collect::>()); + + assert!(cursor.iter_from(b"key6").is_err()); } #[test] @@ -464,7 +468,10 @@ mod test { (b"b", b"3"), (b"c", b"1"), (b"c", b"2"), - (b"c", b"3")); + (b"c", b"3"), + (b"e", b"1"), + (b"e", b"2"), + (b"e", b"3")); { let mut txn = env.begin_rw_txn().unwrap(); @@ -491,6 +498,9 @@ mod test { assert_eq!(items.clone().into_iter().skip(3).collect::>(), cursor.iter_dup_from(b"ab").unwrap().flat_map(|x| x).collect::>()); + assert_eq!(items.clone().into_iter().skip(9).collect::>(), + cursor.iter_dup_from(b"d").unwrap().flat_map(|x| x).collect::>()); + assert_eq!(items.clone().into_iter().skip(3).take(3).collect::>(), cursor.iter_dup_of(b"b").unwrap().collect::>()); From fe6bcde6c24ec75046a46eb3e3d52700689245f1 Mon Sep 17 00:00:00 2001 From: Myk Melez Date: Thu, 24 May 2018 19:54:30 -0700 Subject: [PATCH 4/4] ignore NotFound error when seeking to key in iter_from/iter_dup_from --- src/cursor.rs | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/cursor.rs b/src/cursor.rs index 11c189a..1f0dc63 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -61,9 +61,13 @@ pub trait Cursor<'txn> { /// For databases with duplicate data items (`DatabaseFlags::DUP_SORT`), the /// duplicate data items of each key will be returned before moving on to /// the next key. - fn iter_from(&mut self, key: K) -> Result> where K: AsRef<[u8]> { - try!(self.get(Some(key.as_ref()), None, ffi::MDB_SET_RANGE)); - Ok(Iter::new(self.cursor(), ffi::MDB_GET_CURRENT, ffi::MDB_NEXT)) + fn iter_from(&mut self, key: K) -> Iter<'txn> where K: AsRef<[u8]> { + match self.get(Some(key.as_ref()), None, ffi::MDB_SET_RANGE) { + Err(Error::NotFound) => Ok(()), + Err(error) => Err(error), + Ok(_) => Ok(()), + }.unwrap(); + Iter::new(self.cursor(), ffi::MDB_GET_CURRENT, ffi::MDB_NEXT) } /// Iterate over duplicate database items. The iterator will begin with the @@ -82,9 +86,13 @@ pub trait Cursor<'txn> { /// Iterate over duplicate items in the database starting from the given /// key. Each item will be returned as an iterator of its duplicates. - fn iter_dup_from(&mut self, key: &K) -> Result> where K: AsRef<[u8]> { - try!(self.get(Some(key.as_ref()), None, ffi::MDB_SET_RANGE)); - Ok(IterDup::new(self.cursor(), ffi::MDB_GET_CURRENT)) + fn iter_dup_from(&mut self, key: &K) -> IterDup<'txn> where K: AsRef<[u8]> { + match self.get(Some(key.as_ref()), None, ffi::MDB_SET_RANGE) { + Err(Error::NotFound) => Ok(()), + Err(error) => Err(error), + Ok(_) => Ok(()), + }.unwrap(); + IterDup::new(self.cursor(), ffi::MDB_GET_CURRENT) } /// Iterate over the duplicates of the item in the database with the given @@ -446,12 +454,13 @@ mod test { assert_eq!(items, cursor.iter_start().collect::>()); assert_eq!(items.clone().into_iter().skip(1).collect::>(), - cursor.iter_from(b"key2").unwrap().collect::>()); + cursor.iter_from(b"key2").collect::>()); assert_eq!(items.clone().into_iter().skip(3).collect::>(), - cursor.iter_from(b"key4").unwrap().collect::>()); + cursor.iter_from(b"key4").collect::>()); - assert!(cursor.iter_from(b"key6").is_err()); + assert_eq!(vec!().into_iter().collect::>(), + cursor.iter_from(b"key6").collect::>()); } #[test] @@ -493,18 +502,20 @@ mod test { cursor.iter_dup_start().flat_map(|x| x).collect::>()); assert_eq!(items.clone().into_iter().skip(3).collect::>(), - cursor.iter_dup_from(b"b").unwrap().flat_map(|x| x).collect::>()); + cursor.iter_dup_from(b"b").flat_map(|x| x).collect::>()); assert_eq!(items.clone().into_iter().skip(3).collect::>(), - cursor.iter_dup_from(b"ab").unwrap().flat_map(|x| x).collect::>()); + cursor.iter_dup_from(b"ab").flat_map(|x| x).collect::>()); assert_eq!(items.clone().into_iter().skip(9).collect::>(), - cursor.iter_dup_from(b"d").unwrap().flat_map(|x| x).collect::>()); + cursor.iter_dup_from(b"d").flat_map(|x| x).collect::>()); + + assert_eq!(vec!().into_iter().collect::>(), + cursor.iter_dup_from(b"f").flat_map(|x| x).collect::>()); assert_eq!(items.clone().into_iter().skip(3).take(3).collect::>(), cursor.iter_dup_of(b"b").unwrap().collect::>()); - assert!(cursor.iter_dup_from(b"foo").is_err()); assert!(cursor.iter_dup_of(b"foo").is_err()); }