Common function using diesel causes overflow

I have an API written in Rust, and the goal is to set ~ 15 tables in the database. I wrote some very similar functions to expose each table, so I thought that I would take cracks in polymorphism to simplify the code.

I reduced all the code to one file:

#[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);
}

This is my Cargo.toml file

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

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

When I try to run this, I get the following compiler error:

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

The compiler tells me that I can solve the problem by increasing the recursion limit, but I tried to do this to 8096, and the error was still not resolved.

+4
source share
1 answer

You are not far off:

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!()
}

Note:

  • , . Find.

  • . FindDsl QueryDsl - , , , . QueryDsl , Find, QueryDsl::find :

    fn find<PK>(self, id: PK) -> Find<Self, PK>
    where
        Self: FindDsl<PK>,
    
  • load Vec , . , get_result first?

  • , , Serde Diesel; .

+3

Source: https://habr.com/ru/post/1692835/


All Articles