gpt4 book ai didi

generics - 使用 Diesel 的通用函数会导致溢出

转载 作者:行者123 更新时间:2023-11-29 07:51:05 25 4
gpt4 key购买 nike

我有一个用 Rust 编写的 API,它的目标是在数据库中公开约 15 个表。我已经编写了几个非常相似的函数来公开每个表,所以我想我应该尝试一下多态性来简化代码。

我已将所有代码缩减到一个文件中:

#[macro_use]
extern crate diesel;
extern crate dotenv;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

table! {
table1 (id) {
id -> Int4,
value -> Text,
}
}

table! {
table2 (id) {
id -> Int4,
value -> Text,
}
}

#[derive(Identifiable, Queryable, Serialize)]
#[table_name = "table1"]
struct Model1 {
pub id: i32,
pub value: String,
}

#[derive(Identifiable, Queryable, Serialize)]
#[table_name = "table2"]
struct Model2 {
pub id: i32,
pub value: String,
}

use dotenv::dotenv;
use std::env;

fn get_connection() -> PgConnection {
dotenv().ok();
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
PgConnection::establish(&database_url).expect("Database not working")
}

use diesel::QueryDsl;
use diesel::pg::PgConnection;
use diesel::query_dsl::LoadQuery;
use diesel::result::Error;
use diesel::query_dsl::filter_dsl::FindDsl;
use serde::Serialize;
use serde_json::to_string;

fn get_row<'a, Model, Table>(table: Table, id: i32) -> Result<String, Error>
where
Table: QueryDsl,
<Table as FindDsl<i32>>::Output: LoadQuery<PgConnection, Model>,
Model: Serialize,
{
let result: Model = table.find(id).load(&get_connection())?;
Ok(to_string(&result)?)
}

fn main() {
let row1 = get_row::<Model1, _>(table1::table, 1);
let row2 = get_row::<Model2, _>(table2::table, 1);
}

这是我的 Cargo.toml 文件

[package]
name = "question"
version = "0.1.0"

[dependencies]
diesel = { version = "*", features = ["postgres"] }
diesel_codegen = "*"
serde = "*"
serde_derive = "*"
serde_json = "*"
dotenv = "*"

当我尝试运行它时,出现以下编译器错误:

error[E0275]: overflow evaluating the requirement `<Table as diesel::query_dsl::filter_dsl::FilterDsl<_>>::Output`
--> src/main.rs:54:1
|
54 | / fn get_row<'a, Model, Table>(table: Table, id: i32) -> Result<String, Error>
55 | | where
56 | | Table: QueryDsl,
57 | | <Table as FindDsl<i32>>::Output: LoadQuery<PgConnection, Model>,
... |
61 | | Ok(to_string(&result)?)
62 | | }
| |_^
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate

编译器告诉我可以通过增加递归限制来解决问题,但我尝试将其提高到 8096,但错误仍未解决。

最佳答案

你离得不远:

use diesel::dsl::Find;
use diesel::pg::PgConnection;
use diesel::query_dsl::{LoadQuery, RunQueryDsl};
use diesel::query_dsl::filter_dsl::FindDsl;
use diesel::result::Error;

fn get_row<'a, Model, Table>(table: Table, id: i32) -> Result<String, Error>
where
Table: FindDsl<i32>,
Find<Table, i32>: LoadQuery<PgConnection, Model>,
{
let conn = get_connection();
let result = table.find(id).load::<Model>(&conn)?;
unimplemented!()
}

注意事项:

  1. Diesel 有一堆辅助类型别名,可以更轻松地编写 trait bounds。这里使用了 Find 别名。

  2. 使用更具体的特征边界而不是不太具体的特征边界会更明显。在这里,切换到 FindDsl 而不是 QueryDsl 可能是代码编译的原因。 QueryDsl 并不意味着您可以调用 find 作为 QueryDsl::find method actually has further trait bounds :

    fn find<PK>(self, id: PK) -> Find<Self, PK>
    where
    Self: FindDsl<PK>,
  3. load 的返回值是结果的 Vec,但您已将该类型注释为单个值。也许您想改用 get_resultfirst

  4. 我删除了特定于 Serde 的代码,因为没有明显的方法可以将 Serde 错误转换为 Diesel 错误;这取决于你。

关于generics - 使用 Diesel 的通用函数会导致溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48487871/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com