I have an API written in Rust and it's goal is to expose ~15 tables in a database. I've written several very similar functions to expose each table so I thought I'd take a crack at polymorphism to simplify the code.
I've reduced all the code to a single 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 might resolve the issue by increasing the recursion limit, but I tried doing that up to 8096 and the error still wasn't resolved.
If you suspect you have DEF in your diesel’s fuel system, do not drive the vehicle and do not attempt to start the engine. Don’t even turn the key on, as this will energize the fuel system and could pump DEF-contaminated fuel into the rest of the fuel system.
When the day tank (freestanding or generator sub-base mounted) is served by an underground storage tank (below grade), the return of overflow fuel may be possible by gravity alone.
The National Fire Protection Association (NFPA) addresses fuel overflow by stating that any fuel tank filled by a pump shall be equipped with an overflow return line (NFPA 37 6.5.4, 6.5.4.1, 6.5.4.2). Of key importance, NFPA also requires that this overflow return line be routed “back to the source tank, or to a collection system”.
1. Coolant Leaks Coolant Leaks are the primary cause of overheating in diesel engines and can be easily identified, as you will notice either a low coolant level or an excessive amount of bubbles in the coolant. This can be a result of engine components, such as the cylinder head, expanding due to excess heat.
You weren't 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!()
}
Points to note:
Diesel has a bunch of helper type aliases which make writing trait bounds easier. Here, the Find
alias has been used.
It can be more obvious to use more specific trait bounds instead of less specific ones. Here, switching to FindDsl
instead of QueryDsl
is probably what makes the code compile. QueryDsl
doesn't mean that you can call find
as the QueryDsl::find
method actually has further trait bounds:
fn find<PK>(self, id: PK) -> Find<Self, PK>
where
Self: FindDsl<PK>,
The return value of load
is a Vec
of results, but you had annotated the type as a single value. Perhaps you wanted to use get_result
or first
instead?
I removed the Serde-specific code because there's no obvious way to convert the Serde error to a Diesel error; that's up to you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With