Skip to content

Commit

Permalink
add bugfixes and breaking changes for v0.3
Browse files Browse the repository at this point in the history
- closes #5: bugfix for any filter maps:
  rows with an any value can now also match otherwise
  unknown variants of this filter map type
- closes #6: QoL improvement that can break some users,
  where the db queries now accept for filter maps
  'impl Into<T>' instead of 'T', making it especially
  for newtype-like filter map types easier to use
  • Loading branch information
GlenDC committed Apr 18, 2024
1 parent 389fb94 commit c5d4f5f
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 26 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

# 0.3.0 (2024-04-18)

Breaking changes:

* [[`#6`](https://github.com/plabayo/venndb/issues/6)] query filter maps now accept arguments as `impl Into<T>` instead of `T`,
this can be a breaking change for users that were inserting them as `value.into()`,
as the compiler will for these cases now give a compile time error due to the now introduced ambiguity;
* Migration is as easy as removing the manual `.into()` (like) calls that you previously had to add yourself;

Bug Fixes from [0.2.1](#021-2024-04-15):

* [[`#5`](https://github.com/plabayo/venndb/issues/5)] any filters now also allow rows to match on unknown filter map variants.
* e.g. if you have a `MyType` filter map and have not a single row that has `"foo"` as value,
then all rows that that have a value for which `assert!(Any::is_any(value: MyType))` will still work.
* prior to this bug fix these values could not be matched on, and the `any` rows would only hit
if there were also rows that had that value explicitly defined.

# 0.2.1 (2024-04-15)

A backwards compatible patch for [v0.2.0](#020-2024-04-15),
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ repository = "https://github.com/plabayo/venndb"
keywords = ["database", "db", "memory", "bits"]
categories = ["database"]
authors = ["Glen De Cauwsemaecker <glen@plabayo.tech>"]
version = "0.2.1"
version = "0.3.0"
rust-version = "1.75.0"

[package.metadata.docs.rs]
Expand All @@ -23,7 +23,7 @@ rustdoc-args = ["--cfg", "docsrs"]
bitvec = "1.0.1"
hashbrown = "0.14.3"
rand = "0.8.5"
venndb-macros = { version = "0.2.1", path = "venndb-macros" }
venndb-macros = { version = "0.3.0", path = "venndb-macros" }

[dev-dependencies]
divan = "0.1.14"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ Query (e.g. `EmployeeInMemDBQuery`)
| `EmployeeInMemDBQuery::reset(&mut self) -> &mut Self` | reset the query, bringing it back to the clean state it has on creation |
| `EmployeeInMemDBQuery::execute(&self) -> Option<EmployeeInMemDBQueryResult<'a>>` | return the result of the query using the set filters. It will be `None` in case no rows matched the defined filters. Or put otherwise, the result will contain at least one row when `Some(_)` is returned. |
| `EmployeeInMemDBQuery::is_manager(&mut self, value: bool) -> &mut Self` | a filter setter for a `bool` filter. One such method per `bool` filter (that isn't `skip`ped) will be available. E.g. if you have ` foo` filter then there will be a `EmployeeInMemDBQuery:foo` method. For _bool_ filters that are optional (`Option<bool>`) this method is also generated just the same. |
| `EmployeeInMemDBQuery::department(&mut self, value: Department) -> &mut Self` | a filter (map) setter for a non-`bool` filter. One such method per non-`bool` filter will be available. You can also `skip` these, but that's of course a bit pointless. The type will be equal to the actual field type. And the name will once again be equal to the original field name. Filter maps that have a `Option<T>` type have exactly the same signature. |
| `EmployeeInMemDBQuery::department(&mut self, value: impl ::std::convert::Into<Department>) -> &mut Self` | a filter (map) setter for a non-`bool` filter. One such method per non-`bool` filter will be available. You can also `skip` these, but that's of course a bit pointless. The type will be equal to the actual field type. And the name will once again be equal to the original field name. Filter maps that have a `Option<T>` type have exactly the same signature. |

Query Result (e.g. `EmployeeInMemDBQueryResult`)

Expand Down
6 changes: 3 additions & 3 deletions benches/proxies/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl ProxyDB for InMemProxyDB {

fn any_tcp(&self, pool: &str, country: &str) -> Option<Cow<Proxy>> {
let mut query = self.query();
query.tcp(true).pool(pool.into()).country(country.into());
query.tcp(true).pool(pool).country(country);
query.execute().map(|result| {
let proxy_ref = result.any();
Cow::Borrowed(proxy_ref)
Expand All @@ -107,8 +107,8 @@ impl ProxyDB for InMemProxyDB {
.socks5(true)
.datacenter(true)
.residential(true)
.pool(pool.into())
.country(country.into());
.pool(pool)
.country(country);
query.execute().map(|result| {
let proxy_ref = result.any();
Cow::Borrowed(proxy_ref)
Expand Down
2 changes: 1 addition & 1 deletion venndb-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ repository = "https://github.com/plabayo/venndb"
keywords = ["database", "db", "memory", "bits"]
categories = ["database", "db"]
authors = ["Glen De Cauwsemaecker <glen@plabayo.tech>"]
version = "0.2.1"
version = "0.3.0"
rust-version = "1.75.0"

[package.metadata.docs.rs]
Expand Down
44 changes: 25 additions & 19 deletions venndb-macros/src/generate_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,14 @@ fn generate_db_struct_method_append(
};

let filter_any_register = match field.filter_any_name() {
Some(name) => quote! {
self.#name.push(::venndb::Any::is_any(&value));
Some(any_vec) => if field.optional {
quote! {
self.#any_vec.push(data.#name.as_ref().map(::venndb::Any::is_any).unwrap_or_default());
}
} else {
quote! {
self.#any_vec.push(::venndb::Any::is_any(&data.#name));
}
},
None => quote! {},
};
Expand Down Expand Up @@ -441,9 +447,9 @@ fn generate_db_struct_method_append(

if field.optional {
quote! {
#filter_any_register
let #filter_index = match data.#name.clone() {
Some(value) => {
#filter_any_register
Some(match self.#filter_map_name.entry(value) {
::venndb::__internal::hash_map::Entry::Occupied(entry) => *entry.get(),
::venndb::__internal::hash_map::Entry::Vacant(entry) => {
Expand All @@ -462,9 +468,8 @@ fn generate_db_struct_method_append(
}
} else {
quote! {
let value = data.#name.clone();
#filter_any_register
let #filter_index = match self.#filter_map_name.entry(value) {
let #filter_index = match self.#filter_map_name.entry(data.#name.clone()) {
::venndb::__internal::hash_map::Entry::Occupied(entry) => *entry.get(),
::venndb::__internal::hash_map::Entry::Vacant(entry) => {
let vec_index = self.#filter_vec_name.len();
Expand Down Expand Up @@ -700,8 +705,8 @@ fn generate_query_struct_impl(
);
Some(quote! {
#[doc=#doc]
#vis fn #name(&mut self, value: #ty) -> &mut Self {
self.#name = Some(value);
#vis fn #name(&mut self, value: impl::std::convert::Into<#ty>) -> &mut Self {
self.#name = Some(value.into());
self
}
})
Expand Down Expand Up @@ -752,20 +757,21 @@ fn generate_query_struct_impl(
let name = field.name();
let filter_map_name: Ident = field.filter_map_name();
let filter_vec_name: Ident = field.filter_vec_name();
let value_filter = quote! {
match self.db.#filter_map_name.get(value) {
Some(index) => filter &= &self.db.#filter_vec_name[*index],
None => return None,
};
};
let value_filter = if field.any {
quote! {
let value_filter = match field.filter_any_name() {
Some(filter_any_vec) => quote! {
if !::venndb::Any::is_any(&value) {
#value_filter
match self.db.#filter_map_name.get(value) {
Some(index) => filter &= &self.db.#filter_vec_name[*index],
None => filter &= &self.db.#filter_any_vec,
};
}
}
} else {
value_filter
},
None => quote! {
match self.db.#filter_map_name.get(value) {
Some(index) => filter &= &self.db.#filter_vec_name[*index],
None => return None,
};
},
};
Some(quote! {
// Filter by the filterm ap below, only if it is defined as Some(_).
Expand Down
53 changes: 53 additions & 0 deletions venndb-usage/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -999,3 +999,56 @@ mod tests_v0_2_1 {
assert_eq!(results[1].id, 3);
}
}

#[cfg(test)]
mod tests_v0_2_2 {
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_white_rabbit() {
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: None,
department: None,
},
Worker {
id: 3,
is_admin: false,
is_active: Some(true),
department: Some(Department::Any),
},
Worker {
id: 4,
is_admin: false,
is_active: Some(true),
department: Some(Department::HR),
},
])
.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);
}
}

0 comments on commit c5d4f5f

Please sign in to comment.