I would like to build a query and then pass it off to a function wherein it will call diesel_async
's get_results
I can't seem to get the trait constraints correct on the function parameters. I've chased my tail trying to add the trait constraints that Rust complains about, but so far have been unsuccessful.
My latest attempt has been:
use diesel::{debug_query, pg::Pg, BoolExpressionMethods, ExpressionMethods, QueryDsl,
query_builder::QueryFragment, sql_types::SingleValue,
query_builder::QueryId, Queryable, Identifiable
};
use diesel_async::{RunQueryDsl, AsyncPgConnection, AsyncConnection, methods::LoadQuery};
use serde::{Serialize, Deserialize};
type DB = diesel::pg::Pg;
diesel::table! {
foo (id) {
id -> Int4,
label -> Nullable<Text>,
}
}
#[derive(Queryable, Debug, Serialize, Deserialize, Identifiable)]
#[diesel(primary_key(id))]
#[diesel(table_name = foo)]
pub struct Foo {
pub id: i32,
pub label: Option<String>,
}
pub async fn get_results_wrapped<'query, 'conn, QueryType, ResultItemType>(
qry: &QueryType,
conn: & mut AsyncPgConnection
) -> Vec<ResultItemType>
where
QueryType: LoadQuery<'query, AsyncPgConnection, ResultItemType> + 'query,
ResultItemType: Send,
{
qry.get_results::<ResultItemType>(conn).await.unwrap()
}
#[tokio::main]
async fn main() {
let mut conn = AsyncPgConnection::establish(&std::env::var("DATABASE_URL").unwrap()).await.unwrap();
let qry = foo::table.filter(foo::id.eq(foo::id));
// works
let query_str = debug_query::<DB,_>(&qry).to_string();
let results = qry.get_results::<Foo>(& mut conn).await.unwrap();
// doesn't work
let results : Vec<Foo>= get_results_wrapped(&qry, & mut conn).await.unwrap();
}
With Cargo.toml
dependencies:
diesel = { version = "2.2.6", features = ["chrono", "postgres", "uuid", "serde_json"] }
diesel-async = { version ="0.5.2", features = [ "deadpool", "postgres"] }
tokio = { version = "1.40", features = ["full"] }
Rust 1.84.0 complains:
error[E0277]: the trait bound `QueryType: Query` is not satisfied
--> src/main.rs:36:9
|
36 | qry.get_results::<ResultItemType>(conn).await.unwrap()
| ^^^^^^^^^^^ the trait `Query` is not implemented for `QueryType`
|
= note: required for `&QueryType` to implement `Query`
= note: required for `&QueryType` to implement `diesel_async::methods::LoadQuery<'_, _, ResultItemType>`
help: consider further restricting this bound
|
32 | QueryType: LoadQuery<'query, AsyncPgConnection, ResultItemType> + 'query + diesel::query_builder::Query,
| ++++++++++++++++++++++++++++++
error[E0277]: the trait bound `ResultItemType: FromSqlRow<_, _>` is not satisfied
--> src/main.rs:36:9
|
36 | qry.get_results::<ResultItemType>(conn).await.unwrap()
| ^^^^^^^^^^^ the trait `FromSqlRow<_, _>` is not implemented for `ResultItemType`
|
= note: double check your type mappings via the documentation of `_`
= note: `diesel::sql_query` requires the loading target to column names for loading values.
You need to provide a type that explicitly derives `diesel::deserialize::QueryableByName`
= help: the following other types implement trait `FromSqlRow<ST, DB>`:
`T` implements `FromSqlRow<ST, DB>`
`T` implements `FromSqlRow<Untyped, DB>`
= note: required for `&QueryType` to implement `diesel_async::methods::LoadQuery<'_, _, ResultItemType>`
error[E0277]: `&QueryType` cannot be sent between threads safely
--> src/main.rs:36:9
|
36 | qry.get_results::<ResultItemType>(conn).await.unwrap()
| ^^^^^^^^^^^ `&QueryType` cannot be sent between threads safely
|
= note: required for `&QueryType` to implement `Send`
= note: required for `&QueryType` to implement `diesel_async::methods::LoadQuery<'_, _, ResultItemType>`
help: consider further restricting this bound
|
32 | QueryType: LoadQuery<'query, AsyncPgConnection, ResultItemType> + 'query + std::marker::Sync,
| +++++++++++++++++++
error[E0277]: `QueryType` is no valid SQL fragment for the `_` backend
--> src/main.rs:36:9
|
36 | qry.get_results::<ResultItemType>(conn).await.unwrap()
| ^^^^^^^^^^^ the trait `QueryFragment<_>` is not implemented for `QueryType`
|
= note: this usually means that the `_` database system does not support
this SQL syntax
= help: the trait `QueryFragment<_>` is not implemented for `QueryType`
but it is implemented for `&_`
= help: for that trait implementation, expected `&_`, found `QueryType`
= note: required for `&QueryType` to implement `QueryFragment<_>`
= note: required for `&QueryType` to implement `diesel_async::methods::LoadQuery<'_, _, ResultItemType>`
error[E0277]: the trait bound `QueryType: QueryId` is not satisfied
--> src/main.rs:36:9
|
36 | qry.get_results::<ResultItemType>(conn).await.unwrap()
| ^^^^^^^^^^^ the trait `QueryId` is not implemented for `QueryType`
|
= note: required for `&QueryType` to implement `QueryId`
= note: required for `&QueryType` to implement `diesel_async::methods::LoadQuery<'_, _, ResultItemType>`
help: consider further restricting this bound
|
32 | QueryType: LoadQuery<'query, AsyncPgConnection, ResultItemType> + 'query + diesel::query_builder::QueryId,
| ++++++++++++++++++++++++++++++++
error[E0277]: the trait bound `ResultItemType: FromSqlRow<_, _>` is not satisfied
--> src/main.rs:36:39
|
36 | qry.get_results::<ResultItemType>(conn).await.unwrap()
| ----------- ^^^^ the trait `FromSqlRow<_, _>` is not implemented for `ResultItemType`
| |
| required by a bound introduced by this call
|
= note: double check your type mappings via the documentation of `_`
= note: `diesel::sql_query` requires the loading target to column names for loading values.
You need to provide a type that explicitly derives `diesel::deserialize::QueryableByName`
= help: the following other types implement trait `FromSqlRow<ST, DB>`:
`T` implements `FromSqlRow<ST, DB>`
`T` implements `FromSqlRow<Untyped, DB>`
= note: required for `&QueryType` to implement `diesel_async::methods::LoadQuery<'_, _, ResultItemType>`
note: required by a bound in `diesel_async::RunQueryDsl::get_results`
--> /home/ross/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-async-0.5.2/src/run_query_dsl/mod.rs:581:15
|
574 | fn get_results<'query, 'conn, U>(
| ----------- required by a bound in this associated function
...
581 | Self: methods::LoadQuery<'query, Conn, U> + 'query,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_results`
error[E0277]: the trait bound `&QueryType: diesel_async::methods::LoadQuery<'_, _, ResultItemType>` is not satisfied
--> src/main.rs:36:39
|
36 | qry.get_results::<ResultItemType>(conn).await.unwrap()
| ----------- ^^^^ the trait `QueryFragment<_>` is not implemented for `QueryType`
| |
| required by a bound introduced by this call
|
= help: the trait `QueryFragment<_>` is not implemented for `QueryType`
but it is implemented for `&_`
= help: for that trait implementation, expected `&_`, found `QueryType`
= note: required for `&QueryType` to implement `QueryFragment<_>`
= note: required for `&QueryType` to implement `diesel_async::methods::LoadQuery<'_, _, ResultItemType>`
note: required by a bound in `diesel_async::RunQueryDsl::get_results`
--> /home/ross/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-async-0.5.2/src/run_query_dsl/mod.rs:581:15
|
574 | fn get_results<'query, 'conn, U>(
| ----------- required by a bound in this associated function
...
581 | Self: methods::LoadQuery<'query, Conn, U> + 'query,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_results`
error[E0599]: no method named `unwrap` found for struct `Vec<_>` in the current scope
--> src/main.rs:52:73
|
52 | let results : Vec<Foo>= get_results_wrapped(&qry, & mut conn).await.unwrap();
| ^^^^^^
|
help: there is a method `swap` with a similar name, but with different arguments
--> /rustc/9fc6b43126469e3858e2fe86cafb4f0fd5068869/library/core/src/slice/mod.rs:882:5
Question:
How can diesel_async
's get_results
be generically called within a function?
I would like to build a query and then pass it off to a function wherein it will call diesel_async
's get_results
I can't seem to get the trait constraints correct on the function parameters. I've chased my tail trying to add the trait constraints that Rust complains about, but so far have been unsuccessful.
My latest attempt has been:
use diesel::{debug_query, pg::Pg, BoolExpressionMethods, ExpressionMethods, QueryDsl,
query_builder::QueryFragment, sql_types::SingleValue,
query_builder::QueryId, Queryable, Identifiable
};
use diesel_async::{RunQueryDsl, AsyncPgConnection, AsyncConnection, methods::LoadQuery};
use serde::{Serialize, Deserialize};
type DB = diesel::pg::Pg;
diesel::table! {
foo (id) {
id -> Int4,
label -> Nullable<Text>,
}
}
#[derive(Queryable, Debug, Serialize, Deserialize, Identifiable)]
#[diesel(primary_key(id))]
#[diesel(table_name = foo)]
pub struct Foo {
pub id: i32,
pub label: Option<String>,
}
pub async fn get_results_wrapped<'query, 'conn, QueryType, ResultItemType>(
qry: &QueryType,
conn: & mut AsyncPgConnection
) -> Vec<ResultItemType>
where
QueryType: LoadQuery<'query, AsyncPgConnection, ResultItemType> + 'query,
ResultItemType: Send,
{
qry.get_results::<ResultItemType>(conn).await.unwrap()
}
#[tokio::main]
async fn main() {
let mut conn = AsyncPgConnection::establish(&std::env::var("DATABASE_URL").unwrap()).await.unwrap();
let qry = foo::table.filter(foo::id.eq(foo::id));
// works
let query_str = debug_query::<DB,_>(&qry).to_string();
let results = qry.get_results::<Foo>(& mut conn).await.unwrap();
// doesn't work
let results : Vec<Foo>= get_results_wrapped(&qry, & mut conn).await.unwrap();
}
With Cargo.toml
dependencies:
diesel = { version = "2.2.6", features = ["chrono", "postgres", "uuid", "serde_json"] }
diesel-async = { version ="0.5.2", features = [ "deadpool", "postgres"] }
tokio = { version = "1.40", features = ["full"] }
Rust 1.84.0 complains:
error[E0277]: the trait bound `QueryType: Query` is not satisfied
--> src/main.rs:36:9
|
36 | qry.get_results::<ResultItemType>(conn).await.unwrap()
| ^^^^^^^^^^^ the trait `Query` is not implemented for `QueryType`
|
= note: required for `&QueryType` to implement `Query`
= note: required for `&QueryType` to implement `diesel_async::methods::LoadQuery<'_, _, ResultItemType>`
help: consider further restricting this bound
|
32 | QueryType: LoadQuery<'query, AsyncPgConnection, ResultItemType> + 'query + diesel::query_builder::Query,
| ++++++++++++++++++++++++++++++
error[E0277]: the trait bound `ResultItemType: FromSqlRow<_, _>` is not satisfied
--> src/main.rs:36:9
|
36 | qry.get_results::<ResultItemType>(conn).await.unwrap()
| ^^^^^^^^^^^ the trait `FromSqlRow<_, _>` is not implemented for `ResultItemType`
|
= note: double check your type mappings via the documentation of `_`
= note: `diesel::sql_query` requires the loading target to column names for loading values.
You need to provide a type that explicitly derives `diesel::deserialize::QueryableByName`
= help: the following other types implement trait `FromSqlRow<ST, DB>`:
`T` implements `FromSqlRow<ST, DB>`
`T` implements `FromSqlRow<Untyped, DB>`
= note: required for `&QueryType` to implement `diesel_async::methods::LoadQuery<'_, _, ResultItemType>`
error[E0277]: `&QueryType` cannot be sent between threads safely
--> src/main.rs:36:9
|
36 | qry.get_results::<ResultItemType>(conn).await.unwrap()
| ^^^^^^^^^^^ `&QueryType` cannot be sent between threads safely
|
= note: required for `&QueryType` to implement `Send`
= note: required for `&QueryType` to implement `diesel_async::methods::LoadQuery<'_, _, ResultItemType>`
help: consider further restricting this bound
|
32 | QueryType: LoadQuery<'query, AsyncPgConnection, ResultItemType> + 'query + std::marker::Sync,
| +++++++++++++++++++
error[E0277]: `QueryType` is no valid SQL fragment for the `_` backend
--> src/main.rs:36:9
|
36 | qry.get_results::<ResultItemType>(conn).await.unwrap()
| ^^^^^^^^^^^ the trait `QueryFragment<_>` is not implemented for `QueryType`
|
= note: this usually means that the `_` database system does not support
this SQL syntax
= help: the trait `QueryFragment<_>` is not implemented for `QueryType`
but it is implemented for `&_`
= help: for that trait implementation, expected `&_`, found `QueryType`
= note: required for `&QueryType` to implement `QueryFragment<_>`
= note: required for `&QueryType` to implement `diesel_async::methods::LoadQuery<'_, _, ResultItemType>`
error[E0277]: the trait bound `QueryType: QueryId` is not satisfied
--> src/main.rs:36:9
|
36 | qry.get_results::<ResultItemType>(conn).await.unwrap()
| ^^^^^^^^^^^ the trait `QueryId` is not implemented for `QueryType`
|
= note: required for `&QueryType` to implement `QueryId`
= note: required for `&QueryType` to implement `diesel_async::methods::LoadQuery<'_, _, ResultItemType>`
help: consider further restricting this bound
|
32 | QueryType: LoadQuery<'query, AsyncPgConnection, ResultItemType> + 'query + diesel::query_builder::QueryId,
| ++++++++++++++++++++++++++++++++
error[E0277]: the trait bound `ResultItemType: FromSqlRow<_, _>` is not satisfied
--> src/main.rs:36:39
|
36 | qry.get_results::<ResultItemType>(conn).await.unwrap()
| ----------- ^^^^ the trait `FromSqlRow<_, _>` is not implemented for `ResultItemType`
| |
| required by a bound introduced by this call
|
= note: double check your type mappings via the documentation of `_`
= note: `diesel::sql_query` requires the loading target to column names for loading values.
You need to provide a type that explicitly derives `diesel::deserialize::QueryableByName`
= help: the following other types implement trait `FromSqlRow<ST, DB>`:
`T` implements `FromSqlRow<ST, DB>`
`T` implements `FromSqlRow<Untyped, DB>`
= note: required for `&QueryType` to implement `diesel_async::methods::LoadQuery<'_, _, ResultItemType>`
note: required by a bound in `diesel_async::RunQueryDsl::get_results`
--> /home/ross/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-async-0.5.2/src/run_query_dsl/mod.rs:581:15
|
574 | fn get_results<'query, 'conn, U>(
| ----------- required by a bound in this associated function
...
581 | Self: methods::LoadQuery<'query, Conn, U> + 'query,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_results`
error[E0277]: the trait bound `&QueryType: diesel_async::methods::LoadQuery<'_, _, ResultItemType>` is not satisfied
--> src/main.rs:36:39
|
36 | qry.get_results::<ResultItemType>(conn).await.unwrap()
| ----------- ^^^^ the trait `QueryFragment<_>` is not implemented for `QueryType`
| |
| required by a bound introduced by this call
|
= help: the trait `QueryFragment<_>` is not implemented for `QueryType`
but it is implemented for `&_`
= help: for that trait implementation, expected `&_`, found `QueryType`
= note: required for `&QueryType` to implement `QueryFragment<_>`
= note: required for `&QueryType` to implement `diesel_async::methods::LoadQuery<'_, _, ResultItemType>`
note: required by a bound in `diesel_async::RunQueryDsl::get_results`
--> /home/ross/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-async-0.5.2/src/run_query_dsl/mod.rs:581:15
|
574 | fn get_results<'query, 'conn, U>(
| ----------- required by a bound in this associated function
...
581 | Self: methods::LoadQuery<'query, Conn, U> + 'query,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_results`
error[E0599]: no method named `unwrap` found for struct `Vec<_>` in the current scope
--> src/main.rs:52:73
|
52 | let results : Vec<Foo>= get_results_wrapped(&qry, & mut conn).await.unwrap();
| ^^^^^^
|
help: there is a method `swap` with a similar name, but with different arguments
--> /rustc/9fc6b43126469e3858e2fe86cafb4f0fd5068869/library/core/src/slice/mod.rs:882:5
Question:
How can diesel_async
's get_results
be generically called within a function?
1 Answer
Reset to default 0To flesh out @cafece25's comment that solved my problem, simply passing in the query rather than a reference solve my problem:
pub async fn get_results_wrapped< 'query, QueryType, ResultItemType>(
qry: QueryType,
conn: & mut AsyncPgConnection
) -> Vec<ResultItemType>
where
QueryType: LoadQuery<'query, AsyncPgConnection, ResultItemType> + 'query,
ResultItemType: Send,
{
qry.get_results::<ResultItemType>(conn).await.unwrap()
}
His other suggestion did not work for me. Trying to modify the reference to QueryType
was a whole 'nother can of worms of chasing trait errors.
qry: &QueryType
withqry: QueryType
(or alternatively, constrain the reference:where &'query QueryType: LoadQuery<'query, AsyncPgConnection, ResultItemType>
but you might need to fix the lifetimes here) – cafce25 Commented Feb 14 at 16:45