Using your generated queries
Once you have written your queries and generated your Rust code with Clorinde, it's time to use them. Hurray 🎉!
Let's say you have generated your Rust crate into ./clorinde
and added it to your Cargo.toml
, then this is as simple as importing the items you need from it, like so:
#![allow(unused)] fn main() { use clorinde::queries::authors; }
Building the query object
Building a query object starts with either the query function:
#![allow(unused)] fn main() { authors().bind(&client, Some("Greece")); }
or the generated parameter struct:
#![allow(unused)] fn main() { use clorinde::Params; authors().params( &client, AuthorsParams { country: Some("Greece") } ); }
The query function is useful when you have a few obvious parameters, while the parameter struct is more explicit.
Note that in order to use the params
method, you need to import the Params
trait from your (sync or async) Clorinde client.
Queries that don't have a return value (simple insertions, for example) don't generate a query object. Instead, when calling bind
or params
they execute and return the number of rows affected.
Row mapping (optional)
Query objects have a map
method that allows them to transform the query's returned rows without requiring intermediate allocation. The following example is pretty contrived but illustrates how you can use this feature.
#![allow(unused)] fn main() { enum Country { Greece, TheRest } impl<'a> From<&'a str> for Country { fn from(s: &'a str) -> Self { if s == "Greece" { Self::Greece } else { Self::TheRest } } } struct CustomAuthor { full_name: String, country: Country, age: usize, } authors() .bind(&client) .map(|author| { let full_name = format!( "{}, {}", author.last_name.to_uppercase(), author.first_name ); let country = Country::from(author.country); CustomAuthor { full_name, country, age: author.age, } }); }
The result of a map is another query object.
Getting rows out of your queries
Once the query object has been built, use one of the following methods to select the expected number of rows:
opt
: one or zero rows (error otherwise).one
: exactly one row (error otherwise).iter
: iterator of zero or more rows.all
: likeiter
, but collects the rows in aVec
.
Here are some example uses:
#![allow(unused)] fn main() { author_by_id().bind(&client, &0).opt().await?; author_by_id().bind(&client, &0).one().await?; // Error if this author id doesn't exist authors().bind(&client).all().await?; authors().bind(&client).iter().await?.collect::<Vec<_>>(); // Acts the same as the previous line }