问题描述
上下文:锈,库sqlx
问题:如何在不丢失类型检查的情况下从较小的部分组成类似的查询?
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?;
}
文档说:
查询必须是字符串文字,或使用+的字符串文字串联(对于由宏生成的查询很有用),否则它不能被自省(因此不能是动态的或另一个宏的结果)。
您会看到它说“对宏生成的查询很有用”(尽管以后“不能是另一个宏的结果”)
我要解决的问题是,根据条件,我想运行不同但相似的查询(例如,它们都具有相同的列),并且我希望由较小的可重用部分组成查询[
解决方法
您可以使用如下宏来执行此操作
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
}
}
并根据某些条件提供谓词
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,""),};