pub use ledb_types as types;
#[cfg(feature = "ledb-derive")]
pub use ledb_derive::Document;
#[cfg(test)]
#[macro_use]
mod test;
mod collection;
mod document;
mod enumerate;
mod error;
mod filter;
mod float;
mod index;
mod modify;
mod pool;
mod selection;
mod storage;
mod value;
#[macro_use]
mod macros;
pub use ledb_types::{Document, Identifier, IndexKind, KeyField, KeyFields, KeyType, Primary};
#[cfg(feature = "ledb-derive")]
#[doc(hidden)]
pub use ledb_derive::*;
pub use collection::{Collection, DocumentsIterator};
pub use document::{to_value, RawDocument, Value};
pub use error::{Error, Result, ResultWrap};
pub use filter::{Comp, Cond, Filter, Order, OrderKind};
pub use macros::*;
pub use modify::{Action, Modify, WrappedRegex};
pub use storage::{Info, Options, Stats, Storage};
pub use value::KeyData;
use collection::CollectionDef;
use enumerate::{Enumerable, Serial, SerialGenerator};
use index::{Index, IndexDef};
use pool::Pool;
use selection::Selection;
use storage::{DatabaseDef, StorageData};
#[cfg(test)]
mod tests {
use serde::{Deserialize, Serialize};
use serde_json::json;
use super::{
test::test_db, Collection, Document, Identifier, IndexKind, KeyFields, KeyType, Primary,
Result, Value,
};
fn get_id(val: Value) -> Option<Primary> {
if let Value::Map(map) = val {
map.get(&Value::Text("$".into())).and_then(|val| {
if let Value::Integer(id) = val {
Some(*id as u32)
} else {
None
}
})
} else {
None
}
}
macro_rules! assert_found {
($res:expr $(,$exp:expr)*) => {
let ids: Vec<Primary> = vec![$($exp),*];
assert_eq!($res.unwrap().map(|doc: Result<Value>| get_id(doc.unwrap()).unwrap()).collect::<Vec<_>>(), ids)
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct Doc {
pub k: Option<Primary>,
pub s: String,
pub b: bool,
pub i: Vec<i32>,
pub f: Option<f32>,
pub n: Option<SubDoc>,
}
impl Document for Doc {
fn primary_field() -> Identifier {
"k".into()
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct SubDoc {
pub i: i64,
pub a: Vec<String>,
}
fn fill_data(c: &Collection) -> Result<()> {
c.insert(&json!({ "s": "abc", "b": false, "i": [] }))?;
c.insert(
&json!({ "s": "def", "b": false, "i": [1, 2], "n": { "i": 1, "a": ["t1", "t2"] } }),
)?;
c.insert(&json!({ "s": "123", "b": true, "i": [2, 3, 4], "n": { "i": 2, "a": [] } }))?;
c.insert(
&json!({ "s": "xyz", "b": true, "i": [1, 5, 4], "n": { "i": 3, "a": ["t2", "t4"] } }),
)?;
c.insert(&json!({ "s": "321", "b": false, "i": [2], "n": { "i": 2, "a": ["t4", "t1"] } }))?;
c.insert(&json!({ "s": "456", "b": true, "i": [3, 5], "n": { "i": -11, "a": ["t2"] } }))?;
c.insert(&json!({ "s": "" }))?;
Ok(())
}
fn mk_index(c: &Collection) -> Result<()> {
query!(index for c
s str unique,
b bool,
i integer,
f float,
n.i int,
n.a string)
}
#[test]
fn insert_documents() {
let s = test_db("insert").unwrap();
let c = s.collection("test").unwrap();
assert_eq!(query!(insert into c &Doc::default()).unwrap(), 1);
assert_eq!(query!(insert into c &Doc::default()).unwrap(), 2);
assert_eq!(
query!(insert into c {
"s": "",
"b": false,
"i": 0,
"f": 0.0,
"n": {
"i": 0,
"a": []
}
})
.unwrap(),
3
);
}
#[test]
fn get_by_primary() {
let s = test_db("get").unwrap();
let c = s.collection("test").unwrap();
fill_data(&c).unwrap();
assert_eq!(&c.get::<Doc>(1).unwrap().unwrap().s, "abc");
assert_eq!(&c.get::<Doc>(2).unwrap().unwrap().s, "def");
assert_eq!(&c.get::<Doc>(5).unwrap().unwrap().s, "321");
}
#[test]
fn index_before_insert() {
let s = test_db("index_before_insert").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_eq!(
&query!(find Doc in c where s == "abc")
.unwrap()
.next()
.unwrap()
.unwrap()
.s,
"abc"
);
}
#[test]
fn index_after_insert() {
let s = test_db("index_after_insert").unwrap();
let c = s.collection("test").unwrap();
fill_data(&c).unwrap();
mk_index(&c).unwrap();
assert_eq!(
&query!(find Doc in c where s == "abc")
.unwrap()
.next()
.unwrap()
.unwrap()
.s,
"abc"
);
}
#[test]
fn duplicate_unique_by_inserting() {
let s = test_db("duplicate_unique_by_inserting").unwrap();
let c = s.collection("test").unwrap();
assert!(mk_index(&c).is_ok());
assert!(fill_data(&c).is_ok());
assert!(query!(insert into c { "s": "abc" }).is_err());
}
#[test]
fn duplicate_unique_by_indexing() {
let s = test_db("duplicate_unique_by_indexing").unwrap();
let c = s.collection("test").unwrap();
assert!(fill_data(&c).is_ok());
assert!(query!(insert into c { "s": "abc" }).is_ok());
assert!(mk_index(&c).is_err());
}
#[test]
fn order_by_primary() {
let s = test_db("order_by_primary").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c order >), 1, 2, 3, 4, 5, 6, 7);
assert_found!(query!(find in c order <), 7, 6, 5, 4, 3, 2, 1);
}
#[test]
fn order_by_unique() {
let s = test_db("order_by_unique").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_eq!(query!(find Value in c order by s >).unwrap().len(), 7);
assert_found!(query!(find in c order by s >), 7, 3, 5, 6, 1, 2, 4);
assert_found!(query!(find in c order by s <), 4, 2, 1, 6, 5, 3, 7);
}
#[test]
fn find_string_eq() {
let s = test_db("find_string_eq").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_eq!(query!(find Value in c where s == "xyz").unwrap().len(), 1);
assert_found!(query!(find in c where s == "xyz" order >), 4);
assert_found!(query!(find in c where n.a == "t1"), 2, 5);
assert_eq!(
query!(find Value in c where n.a == "t2" order <)
.unwrap()
.len(),
3
);
assert_found!(query!(find in c where n.a == "t2" order desc), 6, 4, 2);
}
#[test]
fn find_bool_eq() {
let s = test_db("find_bool_eq").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c where b == true), 3, 4, 6);
assert_found!(query!(find in c where b == false), 1, 2, 5);
}
#[test]
fn find_int_eq() {
let s = test_db("find_int_eq").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c where i == 1), 2, 4);
assert_found!(query!(find in c where i == 2), 2, 3, 5);
assert_found!(query!(find in c where n.i == 1), 2);
assert_found!(query!(find in c where n.i == 2 order <), 5, 3);
}
#[test]
fn find_string_in() {
let s = test_db("find_string_in").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_eq!(
query!(find Value in c where s of ["abc", "xyz"])
.unwrap()
.len(),
2
);
assert_found!(query!(find in c where s of ["abc", "xyz"] order >), 1, 4);
assert_found!(query!(find in c where n.a of ["t1", "t4"] order >), 2, 4, 5);
assert_eq!(
query!(find Value in c where n.a of ["t2"] order <)
.unwrap()
.len(),
3
);
assert_found!(query!(find in c where n.a of ["t2"] order desc), 6, 4, 2);
}
#[test]
fn find_int_in() {
let s = test_db("find_int_in").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c where i of [1, 5]), 2, 4, 6);
assert_found!(query!(find in c where i of [2]), 2, 3, 5);
assert_found!(query!(find in c where n.i of [1, 3]), 2, 4);
assert_found!(query!(find in c where n.i of [2] order <), 5, 3);
}
#[test]
fn find_int_bw() {
let s = test_db("find_int_bw").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c where i in 2..3), 2, 3, 5, 6);
assert_found!(query!(find in c where n.i in 1..2 order desc), 5, 3, 2);
}
#[test]
fn find_int_gt() {
let s = test_db("find_int_gt").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c where i > 3), 3, 4, 6);
assert_found!(query!(find in c where n.i > 1 order <), 5, 4, 3);
}
#[test]
fn find_int_ge() {
let s = test_db("find_int_ge").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c where i >= 3), 3, 4, 6);
assert_found!(query!(find in c where n.i >= 1 order desc), 5, 4, 3, 2);
}
#[test]
fn find_int_lt() {
let s = test_db("find_int_lt").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c where i < 3), 2, 3, 4, 5);
assert_found!(query!(find in c where n.i < 2 order desc), 6, 2);
}
#[test]
fn find_int_le() {
let s = test_db("find_int_le").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c where i <= 3), 2, 3, 4, 5, 6);
assert_found!(query!(find in c where n.i <= 2 order desc), 6, 5, 3, 2);
}
#[test]
fn find_has() {
let s = test_db("find_has").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c where i?), 2, 3, 4, 5, 6);
assert_found!(query!(find in c where n.i? order desc), 6, 5, 4, 3, 2);
}
#[test]
fn find_and() {
let s = test_db("find_and").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c where b == true && i == 2), 3);
assert_found!(query!(find in c where n.i == 2 && i == 2 order <), 5, 3);
}
#[test]
fn find_or() {
let s = test_db("find_or").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c where b == true || i == 2), 2, 3, 4, 5, 6);
assert_found!(query!(find in c where n.i == 2 || i == 2 order <), 5, 3, 2);
}
#[test]
fn remove_eq_str() {
let s = test_db("remove_eq_str").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c where s == "def"), 2);
assert_eq!(query!(remove from c where s == "def").unwrap(), 1);
assert_found!(query!(find in c where s == "def"));
assert_found!(query!(find in c where s == "abc"), 1);
}
#[test]
fn remove_ge_int() {
let s = test_db("remove_ge_int").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c where i >= 4), 3, 4, 6);
assert_eq!(query!(remove from c where i >= 4).unwrap(), 3);
assert_found!(query!(find in c where i >= 4));
assert_found!(query!(find in c where i >= 2), 2, 5);
}
#[test]
fn update_set_eq_str() {
let s = test_db("update_set_eq_str").unwrap();
let c = s.collection("test").unwrap();
mk_index(&c).unwrap();
fill_data(&c).unwrap();
assert_found!(query!(find in c where s == "def"), 2);
assert_eq!(
query!(update in c modify s = "klm" where s == "def").unwrap(),
1
);
assert_found!(query!(find in c where s == "def"));
assert_found!(query!(find in c where s == "abc"), 1);
assert_found!(query!(find in c where s == "klm"), 2);
}
#[derive(Debug, Clone, Serialize, Deserialize, Document)]
struct RootDoc {
#[document(primary)]
id: Option<Primary>,
#[document(unique)]
title: String,
#[document(nested)]
meta: MetaData,
#[document(nested)]
links: Vec<LinkData>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Document)]
#[document(nested)]
struct MetaData {
#[document(index)]
keywords: Vec<String>,
description: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, Document)]
#[document(nested)]
struct LinkData {
#[document(index)]
title: Vec<String>,
url: String,
#[document(nested)]
meta: MetaData,
}
#[test]
fn derive_primary() {
assert_eq!(MetaData::primary_field().as_ref(), "$");
assert_eq!(LinkData::primary_field().as_ref(), "$");
assert_eq!(RootDoc::primary_field().as_ref(), "id");
}
#[test]
fn derive_key_fields() {
assert_eq!(
MetaData::key_fields(),
KeyFields::new().with_field(("keywords", KeyType::String, IndexKind::Index))
);
assert_eq!(
LinkData::key_fields(),
KeyFields::new()
.with_field(("title", KeyType::String, IndexKind::Index))
.with_field(("meta.keywords", KeyType::String, IndexKind::Index))
);
assert_eq!(
RootDoc::key_fields(),
KeyFields::new()
.with_field(("title", KeyType::String, IndexKind::Unique))
.with_field(("meta.keywords", KeyType::String, IndexKind::Index))
.with_field(("links.title", KeyType::String, IndexKind::Index))
.with_field(("links.meta.keywords", KeyType::String, IndexKind::Index))
);
}
#[test]
fn derived_index() {
let s = test_db("derived").unwrap();
let c = s.collection("test").unwrap();
query!(index RootDoc for c).unwrap();
}
}