Skip to content

Commit

Permalink
correct behaviour of any value filters
Browse files Browse the repository at this point in the history
Closes #7
  • Loading branch information
GlenDC committed Apr 18, 2024
1 parent 9cefa2c commit f69dd87
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 55 deletions.
4 changes: 3 additions & 1 deletion venndb-macros/src/generate_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,9 @@ fn generate_query_struct_impl(
let filter_vec_name: Ident = field.filter_vec_name();
let value_filter = match field.filter_any_name() {
Some(filter_any_vec) => quote! {
if !::venndb::Any::is_any(&value) {
if ::venndb::Any::is_any(&value) {
filter &= &self.db.#filter_any_vec;
} else {
match self.db.#filter_map_name.get(value) {
Some(index) => filter &= &self.db.#filter_vec_name[*index],
None => filter &= &self.db.#filter_any_vec,
Expand Down
251 changes: 197 additions & 54 deletions venndb-usage/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -868,8 +868,77 @@ mod tests_v0_2_1 {
department: Option<Department>,
}

// these two tests are no longer correct since
// the fix introduced in issue https://github.com/plabayo/venndb/issues/7
//
// this is intended. As such these issues have moved to `::tests_v0_4`.
// Check out the above issue if you want to find the motivation why.

// #[test]
// fn test_any_filter_map() {
// let db = EmployeeDB::from_rows(vec![
// Employee {
// id: 1,
// name: "Alice".to_string(),
// is_manager: true,
// is_admin: false,
// is_active: true,
// department: Department::Engineering,
// },
// Employee {
// id: 2,
// name: "Bob".to_string(),
// is_manager: false,
// is_admin: false,
// is_active: true,
// department: Department::HR,
// },
// ])
// .unwrap();

// let mut query = db.query();
// query.department(Department::Any);
// let results = query.execute().unwrap().iter().collect::<Vec<_>>();
// assert_eq!(results.len(), 2);
// assert_eq!(results[0].id, 1);
// assert_eq!(results[1].id, 2);
// }

// #[test]
// fn test_any_option_filter_map() {
// let db = WorkerDB::from_rows(vec![
// Worker {
// id: 1,
// is_admin: false,
// is_active: Some(true),
// department: Some(Department::Engineering),
// },
// Worker {
// id: 2,
// is_admin: false,
// is_active: Some(true),
// department: Some(Department::HR),
// },
// Worker {
// id: 3,
// is_admin: false,
// is_active: None,
// department: None,
// },
// ])
// .unwrap();

// let mut query = db.query();
// query.department(Department::Any);
// let results = query.execute().unwrap().iter().collect::<Vec<_>>();
// assert_eq!(results.len(), 3);
// assert_eq!(results[0].id, 1);
// assert_eq!(results[1].id, 2);
// assert_eq!(results[2].id, 3);
// }

#[test]
fn test_any_filter_map() {
fn test_any_row_filter_map() {
let db = EmployeeDB::from_rows(vec![
Employee {
id: 1,
Expand All @@ -885,21 +954,21 @@ mod tests_v0_2_1 {
is_manager: false,
is_admin: false,
is_active: true,
department: Department::HR,
department: Department::Any,
},
])
.unwrap();

let mut query = db.query();
query.department(Department::Any);
query.department(Department::Engineering);
let results = query.execute().unwrap().iter().collect::<Vec<_>>();
assert_eq!(results.len(), 2);
assert_eq!(results[0].id, 1);
assert_eq!(results[1].id, 2);
}

#[test]
fn test_any_option_filter_map() {
fn test_any_row_optional_filter_map() {
let db = WorkerDB::from_rows(vec![
Worker {
id: 1,
Expand All @@ -910,45 +979,20 @@ mod tests_v0_2_1 {
Worker {
id: 2,
is_admin: false,
is_active: Some(true),
department: Some(Department::HR),
},
Worker {
id: 3,
is_admin: false,
is_active: None,
department: None,
},
])
.unwrap();

let mut query = db.query();
query.department(Department::Any);
let results = query.execute().unwrap().iter().collect::<Vec<_>>();
assert_eq!(results.len(), 3);
assert_eq!(results[0].id, 1);
assert_eq!(results[1].id, 2);
assert_eq!(results[2].id, 3);
}

#[test]
fn test_any_row_filter_map() {
let db = EmployeeDB::from_rows(vec![
Employee {
id: 1,
name: "Alice".to_string(),
is_manager: true,
Worker {
id: 3,
is_admin: false,
is_active: true,
department: Department::Engineering,
is_active: Some(true),
department: Some(Department::Any),
},
Employee {
id: 2,
name: "Bob".to_string(),
is_manager: false,
Worker {
id: 4,
is_admin: false,
is_active: true,
department: Department::Any,
is_active: Some(true),
department: Some(Department::HR),
},
])
.unwrap();
Expand All @@ -958,11 +1002,27 @@ mod tests_v0_2_1 {
let results = query.execute().unwrap().iter().collect::<Vec<_>>();
assert_eq!(results.len(), 2);
assert_eq!(results[0].id, 1);
assert_eq!(results[1].id, 2);
assert_eq!(results[1].id, 3);
}
}

#[cfg(test)]
mod tests_v0_3_0 {
use super::*;

#[derive(Debug, VennDB)]
pub struct Worker {
#[venndb(key)]
id: u32,
is_admin: bool,
is_active: Option<bool>,
#[venndb(filter, any)]
department: Option<Department>,
}

// regression test: <https://github.com/plabayo/venndb/issues/5>
#[test]
fn test_any_row_optional_filter_map() {
fn test_any_row_optional_filter_map_white_rabbit() {
let db = WorkerDB::from_rows(vec![
Worker {
id: 1,
Expand Down Expand Up @@ -992,16 +1052,15 @@ mod tests_v0_2_1 {
.unwrap();

let mut query = db.query();
query.department(Department::Engineering);
query.department(Department::Marketing);
let results = query.execute().unwrap().iter().collect::<Vec<_>>();
assert_eq!(results.len(), 2);
assert_eq!(results[0].id, 1);
assert_eq!(results[1].id, 3);
assert_eq!(results.len(), 1);
assert_eq!(results[0].id, 3);
}
}

#[cfg(test)]
mod tests_v0_3_0 {
mod tests_v0_4 {
use super::*;

#[derive(Debug, VennDB)]
Expand All @@ -1014,9 +1073,67 @@ mod tests_v0_3_0 {
department: Option<Department>,
}

// regression test: <https://github.com/plabayo/venndb/issues/5>
#[test]
fn test_any_row_optional_filter_map_white_rabbit() {
fn test_any_filter_map() {
let db = EmployeeDB::from_rows(vec![
Employee {
id: 1,
name: "Alice".to_string(),
is_manager: true,
is_admin: false,
is_active: true,
department: Department::Engineering,
},
Employee {
id: 2,
name: "Bob".to_string(),
is_manager: false,
is_admin: false,
is_active: true,
department: Department::HR,
},
])
.unwrap();

let mut query = db.query();
query.department(Department::Any);

// no row matches the filter,
// given all rows have an explicit department value
assert!(query.execute().is_none());
}

#[test]
fn test_any_filter_map_match() {
let db = EmployeeDB::from_rows(vec![
Employee {
id: 1,
name: "Alice".to_string(),
is_manager: true,
is_admin: false,
is_active: true,
department: Department::Engineering,
},
Employee {
id: 2,
name: "Bob".to_string(),
is_manager: false,
is_admin: false,
is_active: true,
department: Department::Any,
},
])
.unwrap();

let mut query = db.query();
query.department(Department::Any);

let employee = query.execute().unwrap().any();
assert_eq!(employee.id, 2);
}

#[test]
fn test_any_option_filter_map() {
let db = WorkerDB::from_rows(vec![
Worker {
id: 1,
Expand All @@ -1027,28 +1144,54 @@ mod tests_v0_3_0 {
Worker {
id: 2,
is_admin: false,
is_active: Some(true),
department: Some(Department::HR),
},
Worker {
id: 3,
is_admin: false,
is_active: None,
department: None,
},
])
.unwrap();

let mut query = db.query();
query.department(Department::Any);

// no row matches the filter,
// given all rows have an explicit department value
assert!(query.execute().is_none());
}

#[test]
fn test_any_option_filter_map_match() {
let db = WorkerDB::from_rows(vec![
Worker {
id: 3,
id: 1,
is_admin: false,
is_active: Some(true),
department: Some(Department::Any),
department: Some(Department::Engineering),
},
Worker {
id: 4,
id: 2,
is_admin: false,
is_active: Some(true),
department: Some(Department::HR),
department: Some(Department::Any),
},
Worker {
id: 3,
is_admin: false,
is_active: None,
department: None,
},
])
.unwrap();

let mut query = db.query();
query.department(Department::Marketing);
let results = query.execute().unwrap().iter().collect::<Vec<_>>();
assert_eq!(results.len(), 1);
assert_eq!(results[0].id, 3);
query.department(Department::Any);

let employee = query.execute().unwrap().any();
assert_eq!(employee.id, 2);
}
}

0 comments on commit f69dd87

Please sign in to comment.