在Diesel ORM中,如何指定表示"任意可查询表"的Trait约束?
在Diesel ORM中,如何指定表示"任意可查询表"的Trait约束?
我来帮你梳理下这个问题哈~你想写一个能处理任意Diesel可查询表的通用函数(比如判断表是否为空),只靠impl QueryDsl确实不够,因为它只覆盖了基础查询能力,还需要补充几个关键的Trait约束才能让编译器认可。
咱们先看你要实现的「判断表是否为空」场景,正确的函数约束应该是这样的:
use anyhow::Result; use diesel::{dsl::{exists, select}, prelude::*, SqliteConnection}; pub fn is_table_empty<T>(db: &mut SqliteConnection, table: T) -> Result<bool> where T: QueryDsl + AsQuery, T::Query: diesel::query_builder::QueryFragment<Sqlite> + LoadQuery<SqliteConnection, bool>, { let exists_query = select(exists(table)); Ok(exists_query.get_result(db)?.not()) }
我给你拆解下每个约束的作用:
QueryDsl:这是Diesel查询的基础Trait,让你的表类型支持各种查询操作符,是必不可少的基础约束AsQuery:保证传入的表类型可以被转换为一个Diesel可识别的查询对象,这样我们才能用exists宏把它包裹起来做存在性检查T::Query: QueryFragment<Sqlite>:确保生成的查询能被Sqlite后端正确解析并生成对应的SQL语句LoadQuery<SqliteConnection, bool>:确保这个查询可以在Sqlite连接上执行,并且最终能返回bool类型的结果(因为exists查询返回的是是否存在记录,取反就是表是否为空)
如果想让这个函数更通用,不绑定到Sqlite数据库,还可以改成泛型后端的版本:
use anyhow::Result; use diesel::{dsl::{exists, select}, prelude::*, connection::Connection}; pub fn is_table_empty<T, Conn, DB>(db: &mut Conn, table: T) -> Result<bool> where Conn: Connection<Backend = DB>, DB: diesel::backend::Backend, T: QueryDsl + AsQuery, T::Query: diesel::query_builder::QueryFragment<DB> + LoadQuery<Conn, bool>, { let exists_query = select(exists(table)); Ok(exists_query.get_result(db)?.not()) }
这样不管是Postgres、MySQL还是其他Diesel支持的数据库,这个函数都能正常工作啦。
之前你只加impl QueryDsl编译失败,核心原因是它只解决了「表能被查询」的基础能力,但没解决「这个查询能被特定数据库执行、能返回预期结果」这些关键要求,所以必须补充上面的几个Trait约束才行。
备注:内容来源于stack exchange,提问作者goose_lake
相关产品推荐
相关产品推荐

