Expand description
§Criterium
Criterium is a framework that makes it easier to implement dynamic queries to databases.
It does so by supplying the needed datastructures that can be compiled to SQL and a list of values (other query languages should be possible too).
It currently integrates with rusqlite. (If the rusqlite
feature flag is set.)
Note: Criterium is currently unfinished and querying of multiple tables isn’t figured out at the time of writing.
License: LGPL-3.0-only
§How does it work?
Usually when building database query one starts out with a relatively simple function:
fn fetch_bookmark_information(
is_favorite: Option<bool>,
name_contains: Option<String>,
tags: Vec<String>,
but_not_tags: Vec<String>,
// …
) -> Vec<Bookmark>;
But as you can see even from this simple example: This won’t scale very well and writing the SQL generation for that by hand is a tedious nightmare (even when switching over to structs).
And most of the time one doesn’t even need all the options available. This is where Criterium comes in.
With Criterium you have an enum that describes all the possible queries for a datatype.
enum BookmarkCriterium {
IsFavorite(BooleanCriterium),
Name(StringCriterium),
HasTag(StringCriterium),
// …
}
impl ToRusqliteQuery for BookmarkCriterium {
fn get_sql_where(&self) -> String {
match self {
Self::IsFavorite(c) => c.get_sql_where("favorite".to_string()),
Self::Name(c) => c.get_sql_where("name".to_string()),
}
}
fn get_where_values(&self) -> Vec<Value> {
match self {
Self::IsFavorite(c) => c.get_where_values(),
Self::Name(c) => c.get_where_values(),
}
}
}
Note: Not all of the datatypes of the example are implemented yet, but it should be pretty straigtforward to implement them outside of Criterium.
Multiple of these are then combined using a CriteriumChain
:
let chain_builder: CriteriumChainBuilder<BookmarkCriterium> =
CriteriumChainBuilder::and(true);
chain_builder.add_criterium(
BookmarkCriterium::IsFavorite(true.into()));
chain_builder.add_criterium(
BookmarkCriterium::HasTag("tag".into()));
chain_builder.add_criterium(
BookmarkCriterium::HasTag(StringCriterium::HasPrefix("useful:")));
chain_builder.add_criterium(
BookmarkCriterium::Name(StringCriterium::Contains("foo")));
let bookmarks = database.query_bookmarks(chain_builder.to_chain());
While at first glance this looks more verbose (it is) this can be assembled on the fly and is more flexible (Noticed how I snug a prefix match on a tag in there?).
The SQL in the background simply has a WHERE
with the output of the chain.get_sql_where()
concatenated after and the values taken from chain.get_where_values()
, you only have to provide the values your Criterium relies on in the SQL query.
As you can tell this is useful when there are a lot of things to query for, and also pretty opinioated, it may oe may not fit your project.
Isn’t that an Object Relational Model (ORM) like in django?
Yes, kind of. But very lightweight and barebones … and the compiler can verify most of it for you.
§What is in here?
Note: If you are reding this from the rust domunetation, the links are broken.
- boolean - A Criterium for matching boolean values.
- rusqlite.rs - Rusqlite integration.
- number - A Criterium for matching numbers.
- rusqlite.rs - Rusqlite integration.
- string - A Criterium for matching text.
- rusqlite.rs - Rusqlite integration.
- search - A Criterium for integrating full text search capabilities.
- chain - A Criterium for connecting other criteria with boolean operators
- builder.rs - A builder struct to make it easier to construct chains.
- rusqlite.rs - Rusqlite integration.
- rusqlite.rs - Traits for integrating with rusqlite.
§Feature Flags
By default all integrations that require external crates are disabled. More integrations to come soonish™.
rusqlite
- This enables rusqlite integration
§Concepts
§Criterium
A Criterium is a datastructure that describes a condition that matches against one or more values, the comparison either results in a match or in a not-match. Criteria themselves usually don’t do any matching as thwir primary purpose is to be compiled to some form of query language.
§Null Values
Criterium uses null
, undefined
and None
and “unset” interchangably all of them mean that the value is not defined and therefore not equals to any set value. Other Comparisons that imply a presence of a value on the other side of the operator must fail. (Similar to how SQL works)
The primitives have an IsNone
matcher to detect the absence or undefinedness of a value.
§Chain
A CriteriumChain is a way to connect multiple criteria with each other and is a Criterium itself. Usually complex queries take in a CriteriumChain with the containing type set to a custom enum that represents all the possible Criteria that are available.
§Inverting
Inverting is used throughout Criterium to describe the process of negating the match-result, either by adding or removing a Not
statement or by changing an operator.
(in most progamming languages the boolean operator for this is not
or !
.)
Re-exports§
pub use boolean::BooleanCriterium;
pub use chain::builder::CriteriumChainBuilder;
pub use chain::CriteriumChain;
pub use chain::ChainInto;
pub use number::NumberCriterium;
pub use string::StringCriterium;
Modules§
- A Boolean type for Criterium
- Combines multiple criteria.
- Matches against numeric values.
- Full Text Search Criterium
- General SQL helpers.
- Matches against textual values.
Enums§
- A way to describe how nultiple elements are joined together in a chain of multiple.