Context: rust, library sqlx
Question: how to compose similar queries from smaller parts, without losing type check?
macro_rules! select {
() => {"select col from tab"}
}
macro_rules! guard1 {
() => {"where col > 1"}
}
macro_rules! guard2 {
() => {"where col > 2"}
}
let mut conn = get_pg_connection_from_somewhere();
if some_condition() {
sqlx::query!(select!() + guard1!()).fetch_all(&mut conn).await?;
} else {
sqlx::query!(select!() + guard2!()).fetch_all(&mut conn).await?;
}
The documentation says that:
The query must be a string literal, or concatenation of string literals using + (useful for queries generated by macro), or else it cannot be introspected (and thus cannot be dynamic or the result of another macro).
You can see that it says that "useful for queries generated by macro" (although later "cannot be the result of another macro")
The problem I want to solve is that, depending on the condition, I want to run different but similar (e.g. they all have the same columns) queries, and I want to compose the query from smaller reusable parts[
You can do this using a macro like below
macro_rules! fetch_all_todos_with_predicate {
($executor:ident, $predicate:tt) => {
sqlx::query!(
"SELECT id, title, completed_at FROM todos " + $predicate
).fetch_all($executor).await
}
}
And provide the predicate based on some condition
let kind = QueryKind::Complete;
let mut conn = get_pg_connection_from_somewhere();
let result = match kind {
QueryKind::Complete => fetch_all_todos_with_predicate!(conn, "WHERE completed_at IS NOT NULL"),
QueryKind::Incomplete => fetch_all_todos_with_predicate!(conn, "WHERE completed_at IS NULL"),
QueryKind::All => fetch_all_todos_with_predicate!(conn, ""),
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With