最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

rust - How can diesel_async's get_results be wrappered? - Stack Overflow

programmeradmin3浏览0评论

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?

Share Improve this question asked Feb 14 at 16:41 Ross RogersRoss Rogers 24.2k28 gold badges114 silver badges171 bronze badges 2
  • Why do you add a reference? Try replacing qry: &QueryType with qry: 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
  • Flawless Victory. Thank you @cafece25. You nailed it. Post your answer for magical internet points and street cred'. – Ross Rogers Commented Feb 14 at 16:50
Add a comment  | 

1 Answer 1

Reset to default 0

To 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.

发布评论

评论列表(0)

  1. 暂无评论