我很難為這個問題選擇一個準確而簡潔的標題。
這個問題是對@Shepmaster在這里給出的優秀答案的擴展。https://stackoverflow.com/a/47880065/3224771
其中的解決方案是:
use diesel::expression::operators::Desc。
use diesel::helper_types::{Limit, Order};
使用 diesel::query_dsl::methods::{LimitDsl, OrderDsl};
use diesel::query_dsl::LoadQuery;
pub fn get_most_recent_entry<'a, Tbl, Expr, Record> (
conn: &SqliteConnection,
表。Tbl,
時間。Expr,
) -> Result<i32, String>
where?
Expr: 柴油機::ExpressionMethods,
Tbl: OrderDsl<Desc<Expr>>。
Order<Tbl, Desc<Expr>>。LoadQuery<SqliteConnection, Record> LimitDsl,
Limit<Order<Tbl, Desc<Expr>>。LoadQuery<SqliteConnection, Record>,
記錄。時間。
{
表
.order(time.desc()
.first(conn)
.optional()
.map(|x| x.map_or(0, |x| x.time() )
.map_err(|e| format!("Error here! {:?}", e)
}
在上面的片段中,Table和Expression被作為引數提供。如何進一步抽象這個函式,使Table和Expression不需要作為引數傳遞?
我已經知道了如何抽象出Table(見下文),但是我不知道如何洗掉Expression引數,以便該函式可以用于任何包含time列的Table。
use diesel::expression::operators::Desc。
use diesel::helper_types::{Limit, Order};
使用 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,
時間。Expr,
) -> Result<i32,String>
where?
Expr: 柴油機::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>,
記錄。時間。
{
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,
名稱。String。
時間。i32 //記錄創建的時間。
}
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?
//不知道如何為運算式設定trait bounds。
//要表達任何有相同時間列的表
{
Tbl::table()
.order(Tbl::columns::time.desc() //類似這樣的東西
.first(conn)
.optional()
.map(|x| x.map_or(0, |x| x.time() )
.map_err(|e| format!("Error here! {:?}", e)
}
使用 crate::schema::cat。
fn main(){
let conn = pool.get()?
get_most_recent_entry::<cat::dsl::cat, _> (&conn)
}
uj5u.com熱心網友回復:
以這種通用的方式訪問列是不可能的。每一列都是它自己的零大小的結構,放在以表命名的模塊中。(參見"Schema in depth "指南,以了解由table!生成的代碼的詳細資訊)。) Rust并沒有提供任何選項來通過泛型解決同一模塊的不同型別。
這樣寫的話,就可以直接提供你自己的特質,允許你指定相應的列,并為相應的表(或模型,或任何你想要的型別)實作它:
trait MyTimeColumnHelper {
type TimeColumn: Default;
}
impl MyTimeColumnHelper for crate::schemat::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>&gt;。LoadQuery<SqliteConnection, Record>,
記錄。時間。
Tbl::Table: OrderDsl<Desc<MyTimeColumnHelper::TimeColumn>>。
Order<Tbl::Table, Desc<MyTimeColumnHelper::TimeColumn>>。LoadQuery<SqliteConnection, Record> LimitDsl,
Limit<Order<Tbl::Table, Desc<MyTimeColumnHelper::TimeColumn>&gt;。LoadQuery<SqliteConnection, Record>,
記錄。時間。
{
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)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/318594.html
標籤:
