如何访问在 Diesel 中一般访问的表的具体列?
Posted
技术标签:
【中文标题】如何访问在 Diesel 中一般访问的表的具体列?【英文标题】:How to access concrete columns of a table accessed generically in Diesel? 【发布时间】:2021-11-07 19:30:19 【问题描述】:我很难为这个问题选择一个准确而简洁的标题。
这个问题扩展了@Shepmaster 在这里给出的出色答案:https://***.com/a/47880065/3224771
解决办法是:
use diesel::expression::operators::Desc;
use diesel::helper_types::Limit, Order;
use diesel::query_dsl::methods::LimitDsl, OrderDsl;
use diesel::query_dsl::LoadQuery;
pub fn get_most_recent_entry<'a, Tbl, Expr, Record>(
conn: &SqliteConnection,
table: Tbl,
time: Expr,
) -> Result<i32, String>
where
Expr: diesel::ExpressionMethods,
Tbl: OrderDsl<Desc<Expr>>,
Order<Tbl, Desc<Expr>>: LoadQuery<SqliteConnection, Record> + LimitDsl,
Limit<Order<Tbl, Desc<Expr>>>: LoadQuery<SqliteConnection, Record>,
Record: Time,
table
.order(time.desc())
.first(conn)
.optional()
.map(|x| x.map_or(0, |x| x.time()))
.map_err(|e| format!("Error here! :?", e))
在上面的 sn-p 中,Table
和 Expression
作为参数提供。如何进一步抽象此函数,使Table
和Expression
都不必作为参数传递?
我已经知道如何抽象Table
(见下文),但我不知道如何删除Expression
参数,以便该函数可以与包含time
专栏。
use diesel::expression::operators::Desc;
use diesel::helper_types::Limit, Order;
use diesel::query_dsl::methods::LimitDsl, OrderDsl;
use diesel::query_dsl::LoadQuery;
use diesel::SqliteConnection;
use crate::diesel::RunQueryDsl, OptionalExtension;
use diesel::associations::HasTable;
pub trait Time
fn time(&self) -> i32;
pub fn get_most_recent_entry<'a, Tbl, Expr, Record>(
conn: &SqliteConnection,
time: Expr,
) -> Result<i32, String>
where
Expr: diesel::ExpressionMethods,
Tbl: HasTable,
Tbl::Table: OrderDsl<Desc<Expr>>,
Order<Tbl::Table, Desc<Expr>>: LoadQuery<SqliteConnection, Record> + LimitDsl,
Limit<Order<Tbl::Table, Desc<Expr>>>: LoadQuery<SqliteConnection, Record>,
Record: Time,
Tbl::table()
.order(time.desc())
.first(conn)
.optional()
.map(|x| x.map_or(0, |x| x.time()))
.map_err(|e| format!("Error here! :?", e))
更新
类似这样的:
# Cargo.toml
[dependencies]
diesel = version = "1.4.5", features = ["sqlite", "extras"]
#[derive(Queryable)]
pub struct Cat
id: u32,
name: String,
time: i32 //time record created
impl Time for Cat
fn time(&self) -> i32
self.time
pub fn get_most_recent_entry<'a, Tbl, Record>(
conn: &SqliteConnection
) -> Result<i32, String>
where
// Don't know how to setup trait bounds for the expression
// to express any table that has the same time column
Tbl::table()
.order(Tbl::columns::time.desc()) // Something like this
.first(conn)
.optional()
.map(|x| x.map_or(0, |x| x.time()))
.map_err(|e| format!("Error here! :?", e))
use crate::schema::cat;
fn main()
let conn = pool.get()?;
get_most_recent_entry::<cat::dsl::cat, _>(&conn)
【问题讨论】:
这个问题真的很难回答。请添加必要的上下文。这至少包括柴油和生锈正在使用的具体版本,对该函数的示例性调用,尤其是关于什么应该被允许作为时间表达和什么不能作为时间表达的更多细节。由于代码是当前编写的,它在那里接受任意表达式,您不能只在函数内部构造而不会失去功能。 @weiznich 已更新,谢谢 【参考方案1】:不可能以这种通用方式访问列。每列都是它自己的零大小结构,放置在以表命名的模块中。 (有关table!
生成的代码的详细信息,请参阅"Schema in depth" guide)。 Rust 不提供任何选项来通过泛型处理来自同一模块的不同类型。
可以只提供你自己的特性,允许你指定对应的列并为对应的表(或模型,或任何你想要的类型)实现它:
trait MyTimeColumnHelper
type TimeColumn: Default;
impl MyTimeColumnHelper for crate::schema::cat::table
type TimeColumn = crate::schema::cat::time;
这样你的泛型函数就可以绑定到这个额外的特征:
pub fn get_most_recent_entry<'a, Tbl, Record>(
conn: &SqliteConnection
) -> Result<i32, String>
where
MyTimeColumnHelper::TimeColumn: diesel::ExpressionMethods,
Tbl: HasTable + MyTimeColumnHelper,
Tbl::Table: OrderDsl<Desc<MyTimeColumnHelper::TimeColumn>>,
Order<Tbl::Table, Desc<MyTimeColumnHelper::TimeColumn>>: LoadQuery<SqliteConnection, Record> + LimitDsl,
Limit<Order<Tbl::Table, Desc<MyTimeColumnHelper::TimeColumn>>>: LoadQuery<SqliteConnection, Record>,
Record: Time,
Tbl::Table: OrderDsl<Desc<MyTimeColumnHelper::TimeColumn>>,
Order<Tbl::Table, Desc<MyTimeColumnHelper::TimeColumn>>: LoadQuery<SqliteConnection, Record> + LimitDsl,
Limit<Order<Tbl::Table, Desc<MyTimeColumnHelper::TimeColumn>>>: LoadQuery<SqliteConnection, Record>,
Record: Time,
Tbl::table()
.order(MyTimeColumnHelper::TimeColumn::default().desc())
.first(conn)
.optional()
.map(|x| x.map_or(0, |x| x.time()))
.map_err(|e| format!("Error here! :?", e))
【讨论】:
以上是关于如何访问在 Diesel 中一般访问的表的具体列?的主要内容,如果未能解决你的问题,请参考以下文章