【发布时间】:2021-11-07 19:30:19
【问题描述】:
我很难为这个问题选择一个准确而简洁的标题。
这个问题扩展了@Shepmaster 在这里给出的出色答案:https://stackoverflow.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 已更新,谢谢
标签: generics rust rust-diesel