-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9205c8e
commit 602b810
Showing
1 changed file
with
105 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/// consider a struct like this | ||
/// struct Sample { | ||
/// id: u64, | ||
/// value: String, | ||
/// date: String, | ||
/// } | ||
/// We would like to index all of the fields so that we can search for the struct not only by ID | ||
/// but also by value and date. When we index the fields individually in their own tables, it | ||
/// is important that we run all operations within a single transaction to ensure coherence of | ||
/// the indices | ||
/// This test features helper functions for reading and writing the parts of the struct. | ||
/// Note that the reader functions take `Readable` because they might run within a Read | ||
/// Transaction or a Write Transaction. The test demonstrates fetching values via both. | ||
use rkv::{ | ||
MultiStore, | ||
SingleStore, | ||
Rkv, | ||
StoreOptions, | ||
Value, | ||
Writer, | ||
Readable, | ||
}; | ||
|
||
use tempfile::Builder; | ||
|
||
use std::fs; | ||
|
||
|
||
|
||
#[test] | ||
fn read_many() { | ||
let root = Builder::new().prefix("test_txns").tempdir().expect("tempdir"); | ||
fs::create_dir_all(root.path()).expect("dir created"); | ||
let k = Rkv::new(root.path()).expect("new succeeded"); | ||
let mut samplestore = k.open_single("s", StoreOptions::create()).expect("open"); | ||
let mut datestore = k.open_multi("m", StoreOptions::create()).expect("open"); | ||
let mut valuestore = k.open_multi("m", StoreOptions::create()).expect("open"); | ||
|
||
{ | ||
let mut writer = k.write().expect("env write lock"); | ||
|
||
for id in 0..30_u64 { | ||
let value = format!("value{}", id); | ||
let date = format!("2019-06-{}", id); | ||
put_id_field(&mut writer, &mut datestore, &date, id); | ||
put_id_field(&mut writer, &mut valuestore, &value, id); | ||
put_sample(&mut writer, &mut samplestore, id, &value); | ||
} | ||
|
||
// now we read in the same transaction | ||
for id in 0..30_u64 { | ||
let value = format!("value{}", id); | ||
let date = format!("2019-06-{}", id); | ||
let ids = get_ids_by_field(&writer, &datestore, &date); | ||
let ids2 = get_ids_by_field(&writer, &valuestore, &value); | ||
let samples = get_samples(&writer, &samplestore, &ids); | ||
let samples2 = get_samples(&writer, &samplestore, &ids2); | ||
println!("{:?}, {:?}", samples, samples2); | ||
} | ||
} | ||
|
||
{ | ||
let reader = k.read().expect("env read lock"); | ||
for id in 0..30_u64 { | ||
let value = format!("value{}", id); | ||
let date = format!("2019-06-{}", id); | ||
let ids = get_ids_by_field(&reader, &datestore, &date); | ||
let ids2 = get_ids_by_field(&reader, &valuestore, &value); | ||
let samples = get_samples(&reader, &samplestore, &ids); | ||
let samples2 = get_samples(&reader, &samplestore, &ids2); | ||
println!("{:?}, {:?}", samples, samples2); | ||
} | ||
} | ||
} | ||
|
||
fn get_ids_by_field<Txn: Readable>(txn: &Txn, store: &MultiStore, field: &str) -> Vec<u64> { | ||
store | ||
.get(txn, field).expect("get iterator") | ||
.map(|id| match id.expect("field") { | ||
(_, Some(Value::U64(id))) => id, | ||
_ => panic!("getting value in iter"), | ||
}).collect::<Vec<u64>>() | ||
} | ||
|
||
fn get_samples<Txn: Readable>(txn: &Txn, samplestore: &SingleStore, ids: &Vec<u64>) -> Vec<String> { | ||
ids.iter().map(|id| { | ||
let bytes = id.to_be_bytes();; | ||
match samplestore.get(txn, &bytes).expect("fetch sample") { | ||
Some(Value::Str(sample)) => String::from(sample), | ||
Some(_) => panic!("wrong type"), | ||
None => panic!("no sample for this id!"), | ||
} | ||
}).collect::<Vec<String>>() | ||
} | ||
|
||
fn put_sample(txn: &mut Writer, samplestore: &mut SingleStore, id: u64, value: &str) { | ||
let idbytes = id.to_be_bytes(); | ||
samplestore.put(txn, &idbytes, &Value::Str(value)).expect("put id"); | ||
} | ||
|
||
fn put_id_field(txn: &mut Writer, store: &mut MultiStore, field: &str, id: u64) { | ||
store.put(txn, field, &Value::U64(id)).expect("put id"); | ||
} | ||
|