Fix lifetime parameter for iterators (#391)

master
wqfish 5 years ago committed by GitHub
parent 46e0c08af5
commit 24e016a57d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      Cargo.toml
  2. 44
      src/db.rs
  3. 8
      tests/fail/iterator_outlive_db.rs
  4. 10
      tests/fail/iterator_outlive_db.stderr
  5. 8
      tests/test_iterator.rs

@ -23,7 +23,9 @@ zstd = ["librocksdb-sys/zstd"]
zlib = ["librocksdb-sys/zlib"] zlib = ["librocksdb-sys/zlib"]
bzip2 = ["librocksdb-sys/bzip2"] bzip2 = ["librocksdb-sys/bzip2"]
[dependencies] [dependencies]
libc = "0.2" libc = "0.2"
librocksdb-sys = { path = "librocksdb-sys", version = "6.4.6" } librocksdb-sys = { path = "librocksdb-sys", version = "6.4.6" }
[dev-dependencies]
trybuild = "1.0.21"

@ -1106,12 +1106,12 @@ impl DB {
self.cfs.get(name) self.cfs.get(name)
} }
pub fn iterator<'a, 'b: 'a>(&'a self, mode: IteratorMode) -> DBIterator<'b> { pub fn iterator<'a: 'b, 'b>(&'a self, mode: IteratorMode) -> DBIterator<'b> {
let readopts = ReadOptions::default(); let readopts = ReadOptions::default();
self.iterator_opt(mode, &readopts) self.iterator_opt(mode, &readopts)
} }
pub fn iterator_opt<'a, 'b: 'a>( pub fn iterator_opt<'a: 'b, 'b>(
&'a self, &'a self,
mode: IteratorMode, mode: IteratorMode,
readopts: &ReadOptions, readopts: &ReadOptions,
@ -1121,25 +1121,25 @@ impl DB {
/// Opens an iterator using the provided ReadOptions. /// Opens an iterator using the provided ReadOptions.
/// This is used when you want to iterate over a specific ColumnFamily with a modified ReadOptions /// This is used when you want to iterate over a specific ColumnFamily with a modified ReadOptions
pub fn iterator_cf_opt( pub fn iterator_cf_opt<'a: 'b, 'b>(
&self, &'a self,
cf_handle: &ColumnFamily, cf_handle: &ColumnFamily,
readopts: &ReadOptions, readopts: &ReadOptions,
mode: IteratorMode, mode: IteratorMode,
) -> DBIterator { ) -> DBIterator<'b> {
DBIterator::new_cf(self, cf_handle, &readopts, mode) DBIterator::new_cf(self, cf_handle, &readopts, mode)
} }
/// Opens an iterator with `set_total_order_seek` enabled. /// Opens an iterator with `set_total_order_seek` enabled.
/// This must be used to iterate across prefixes when `set_memtable_factory` has been called /// This must be used to iterate across prefixes when `set_memtable_factory` has been called
/// with a Hash-based implementation. /// with a Hash-based implementation.
pub fn full_iterator<'a, 'b: 'a>(&'a self, mode: IteratorMode) -> DBIterator<'b> { pub fn full_iterator<'a: 'b, 'b>(&'a self, mode: IteratorMode) -> DBIterator<'b> {
let mut opts = ReadOptions::default(); let mut opts = ReadOptions::default();
opts.set_total_order_seek(true); opts.set_total_order_seek(true);
DBIterator::new(self, &opts, mode) DBIterator::new(self, &opts, mode)
} }
pub fn prefix_iterator<'a, 'b: 'a, P: AsRef<[u8]>>(&'a self, prefix: P) -> DBIterator<'b> { pub fn prefix_iterator<'a: 'b, 'b, P: AsRef<[u8]>>(&'a self, prefix: P) -> DBIterator<'b> {
let mut opts = ReadOptions::default(); let mut opts = ReadOptions::default();
opts.set_prefix_same_as_start(true); opts.set_prefix_same_as_start(true);
DBIterator::new( DBIterator::new(
@ -1149,22 +1149,30 @@ impl DB {
) )
} }
pub fn iterator_cf(&self, cf_handle: &ColumnFamily, mode: IteratorMode) -> DBIterator { pub fn iterator_cf<'a: 'b, 'b>(
&'a self,
cf_handle: &ColumnFamily,
mode: IteratorMode,
) -> DBIterator<'b> {
let opts = ReadOptions::default(); let opts = ReadOptions::default();
DBIterator::new_cf(self, cf_handle, &opts, mode) DBIterator::new_cf(self, cf_handle, &opts, mode)
} }
pub fn full_iterator_cf(&self, cf_handle: &ColumnFamily, mode: IteratorMode) -> DBIterator { pub fn full_iterator_cf<'a: 'b, 'b>(
&'a self,
cf_handle: &ColumnFamily,
mode: IteratorMode,
) -> DBIterator<'b> {
let mut opts = ReadOptions::default(); let mut opts = ReadOptions::default();
opts.set_total_order_seek(true); opts.set_total_order_seek(true);
DBIterator::new_cf(self, cf_handle, &opts, mode) DBIterator::new_cf(self, cf_handle, &opts, mode)
} }
pub fn prefix_iterator_cf<P: AsRef<[u8]>>( pub fn prefix_iterator_cf<'a: 'b, 'b, P: AsRef<[u8]>>(
&self, &'a self,
cf_handle: &ColumnFamily, cf_handle: &ColumnFamily,
prefix: P, prefix: P,
) -> DBIterator { ) -> DBIterator<'b> {
let mut opts = ReadOptions::default(); let mut opts = ReadOptions::default();
opts.set_prefix_same_as_start(true); opts.set_prefix_same_as_start(true);
DBIterator::new_cf( DBIterator::new_cf(
@ -1176,28 +1184,28 @@ impl DB {
} }
/// Opens a raw iterator over the database, using the default read options /// Opens a raw iterator over the database, using the default read options
pub fn raw_iterator(&self) -> DBRawIterator { pub fn raw_iterator<'a: 'b, 'b>(&'a self) -> DBRawIterator<'b> {
let opts = ReadOptions::default(); let opts = ReadOptions::default();
DBRawIterator::new(self, &opts) DBRawIterator::new(self, &opts)
} }
/// Opens a raw iterator over the given column family, using the default read options /// Opens a raw iterator over the given column family, using the default read options
pub fn raw_iterator_cf(&self, cf_handle: &ColumnFamily) -> DBRawIterator { pub fn raw_iterator_cf<'a: 'b, 'b>(&'a self, cf_handle: &ColumnFamily) -> DBRawIterator<'b> {
let opts = ReadOptions::default(); let opts = ReadOptions::default();
DBRawIterator::new_cf(self, cf_handle, &opts) DBRawIterator::new_cf(self, cf_handle, &opts)
} }
/// Opens a raw iterator over the database, using the given read options /// Opens a raw iterator over the database, using the given read options
pub fn raw_iterator_opt(&self, readopts: &ReadOptions) -> DBRawIterator { pub fn raw_iterator_opt<'a: 'b, 'b>(&'a self, readopts: &ReadOptions) -> DBRawIterator<'b> {
DBRawIterator::new(self, readopts) DBRawIterator::new(self, readopts)
} }
/// Opens a raw iterator over the given column family, using the given read options /// Opens a raw iterator over the given column family, using the given read options
pub fn raw_iterator_cf_opt( pub fn raw_iterator_cf_opt<'a: 'b, 'b>(
&self, &'a self,
cf_handle: &ColumnFamily, cf_handle: &ColumnFamily,
readopts: &ReadOptions, readopts: &ReadOptions,
) -> DBRawIterator { ) -> DBRawIterator<'b> {
DBRawIterator::new_cf(self, cf_handle, readopts) DBRawIterator::new_cf(self, cf_handle, readopts)
} }

@ -0,0 +1,8 @@
use rocksdb::{IteratorMode, DB};
fn main() {
let _iter = {
let db = DB::open_default("foo").unwrap();
db.iterator(IteratorMode::Start)
};
}

@ -0,0 +1,10 @@
error[E0597]: `db` does not live long enough
--> $DIR/iterator_outlive_db.rs:6:9
|
4 | let _iter = {
| ----- borrow later stored here
5 | let db = DB::open_default("foo").unwrap();
6 | db.iterator(IteratorMode::Start)
| ^^ borrowed value does not live long enough
7 | };
| - `db` dropped here while still borrowed

@ -299,7 +299,7 @@ fn test_full_iterator() {
assert!(DB::destroy(&opts, path).is_ok()); assert!(DB::destroy(&opts, path).is_ok());
} }
fn custom_iter(db: &DB) -> impl Iterator<Item = usize> { fn custom_iter<'a>(db: &'a DB) -> impl Iterator<Item = usize> + 'a {
db.iterator(IteratorMode::Start) db.iterator(IteratorMode::Start)
.map(|(_, db_value)| db_value.len()) .map(|(_, db_value)| db_value.len())
} }
@ -316,3 +316,9 @@ fn test_custom_iterator() {
let opts = Options::default(); let opts = Options::default();
assert!(DB::destroy(&opts, path).is_ok()); assert!(DB::destroy(&opts, path).is_ok());
} }
#[test]
fn test_iterator_outlive_db() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/fail/iterator_outlive_db.rs");
}

Loading…
Cancel
Save