Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MultiConnection not usable for queries containing Selectable or boxed queries. #3566

Closed
3 tasks done
weiznich opened this issue Mar 25, 2023 · 1 comment
Closed
3 tasks done
Labels
bug hole in api internal or unreleased api Release Blocker This issue needs to be solved before we can release a new version, it can't be punted to the next

Comments

@weiznich
Copy link
Member

weiznich commented Mar 25, 2023

Setup

Versions

  • Rust:
  • Diesel: e548447
  • Database:
  • Operating System

Feature Flags

  • diesel: sqlite postgres

Problem Description

What are you trying to accomplish?

I've tried the following code:

use diesel::prelude::*;

table! {
    users {
        id -> Integer,
        name -> Text,
    }
}

#[derive(Selectable, Queryable)]
struct User {
    id: i32,
}

#[derive(diesel::MultiConnection)]
enum DbConnection {
    Sqlite(SqliteConnection),
    Pg(PgConnection)
}

fn main() {
    let conn = &mut DbConnection::establish("…").unwrap();

    let u = users::table.into_boxed().load::<(i32, String)>(conn);

    let u = users::table
        .select(User::as_select())
        .load(conn);
}

What is the expected output?

Code compiles

What is the actual output?

Code does not compile:

error[E0277]: the trait bound `BoxedSelectStatement<'_, (diesel::sql_types::Integer, diesel::sql_types::Text), FromClause<users::table>, multi_connection_impl::backend::MultiBackend>: QueryFragment<Sqlite>` is not satisfied
    --> src/main.rs:24:61
     |
24   |     let u = users::table.into_boxed().load::<(i32, String)>(conn);
     |                                       ----                  ^^^^ the trait `QueryFragment<Sqlite>` is not implemented for `BoxedSelectStatement<'_, (diesel::sql_types::Integer, diesel::sql_types::Text), FromClause<users::table>, multi_connection_impl::backend::MultiBackend>`
     |                                       |
     |                                       required by a bound introduced by this call
     |
     = help: the following other types implement trait `QueryFragment<DB, SP>`:
               <BoxedSelectStatement<'a, ST, QS, DB, GB> as QueryFragment<DB, AnsiSqlSelectStatement>>
               <BoxedSelectStatement<'a, ST, QS, DB, GB> as QueryFragment<DB>>
               <BoxedSelectStatement<'a, ST, QS, multi_connection_impl::backend::MultiBackend, GB> as QueryFragment<multi_connection_impl::backend::MultiBackend, MultiSelectStatementSyntax>>
note: required for `BoxedSelectStatement<'_, (Integer, Text), FromClause<table>, MultiBackend>` to implement `QueryFragment<multi_connection_impl::backend::MultiBackend, MultiSelectStatementSyntax>`
    --> src/main.rs:15:10
     |
15   | #[derive(diesel::MultiConnection)]
     |          ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
     = note: the full type name has been written to '/tmp/diesel_test/target/debug/deps/diesel_test-e9839cd4beffff40.long-type-6862964700214725501.txt'
     = note: 1 redundant requirement hidden
     = note: required for `BoxedSelectStatement<'_, (Integer, Text), FromClause<table>, MultiBackend>` to implement `QueryFragment<multi_connection_impl::backend::MultiBackend>`
     = note: the full type name has been written to '/tmp/diesel_test/target/debug/deps/diesel_test-e9839cd4beffff40.long-type-17859806514065189679.txt'
     = note: required for `BoxedSelectStatement<'_, (Integer, Text), FromClause<table>, MultiBackend>` to implement `LoadQuery<'_, DbConnection, (i32, String)>`
     = note: the full type name has been written to '/tmp/diesel_test/target/debug/deps/diesel_test-e9839cd4beffff40.long-type-17859806514065189679.txt'
note: required by a bound in `diesel::RunQueryDsl::load`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/query_dsl/mod.rs:1543:15
     |
1543 |         Self: LoadQuery<'query, Conn, U>,
     |               ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
     = note: this error originates in the derive macro `diesel::MultiConnection` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `BoxedSelectStatement<'_, (diesel::sql_types::Integer, diesel::sql_types::Text), FromClause<users::table>, multi_connection_impl::backend::MultiBackend>: QueryFragment<Pg>` is not satisfied
    --> src/main.rs:24:61
     |
24   |     let u = users::table.into_boxed().load::<(i32, String)>(conn);
     |                                       ----                  ^^^^ the trait `QueryFragment<Pg>` is not implemented for `BoxedSelectStatement<'_, (diesel::sql_types::Integer, diesel::sql_types::Text), FromClause<users::table>, multi_connection_impl::backend::MultiBackend>`
     |                                       |
     |                                       required by a bound introduced by this call
     |
     = help: the following other types implement trait `QueryFragment<DB, SP>`:
               <BoxedSelectStatement<'a, ST, QS, DB, GB> as QueryFragment<DB, AnsiSqlSelectStatement>>
               <BoxedSelectStatement<'a, ST, QS, DB, GB> as QueryFragment<DB>>
               <BoxedSelectStatement<'a, ST, QS, multi_connection_impl::backend::MultiBackend, GB> as QueryFragment<multi_connection_impl::backend::MultiBackend, MultiSelectStatementSyntax>>
note: required for `BoxedSelectStatement<'_, (Integer, Text), FromClause<table>, MultiBackend>` to implement `QueryFragment<multi_connection_impl::backend::MultiBackend, MultiSelectStatementSyntax>`
    --> src/main.rs:15:10
     |
15   | #[derive(diesel::MultiConnection)]
     |          ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
     = note: the full type name has been written to '/tmp/diesel_test/target/debug/deps/diesel_test-e9839cd4beffff40.long-type-6862964700214725501.txt'
     = note: 1 redundant requirement hidden
     = note: required for `BoxedSelectStatement<'_, (Integer, Text), FromClause<table>, MultiBackend>` to implement `QueryFragment<multi_connection_impl::backend::MultiBackend>`
     = note: the full type name has been written to '/tmp/diesel_test/target/debug/deps/diesel_test-e9839cd4beffff40.long-type-17859806514065189679.txt'
     = note: required for `BoxedSelectStatement<'_, (Integer, Text), FromClause<table>, MultiBackend>` to implement `LoadQuery<'_, DbConnection, (i32, String)>`
     = note: the full type name has been written to '/tmp/diesel_test/target/debug/deps/diesel_test-e9839cd4beffff40.long-type-17859806514065189679.txt'
note: required by a bound in `diesel::RunQueryDsl::load`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/query_dsl/mod.rs:1543:15
     |
1543 |         Self: LoadQuery<'query, Conn, U>,
     |               ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
     = note: this error originates in the derive macro `diesel::MultiConnection` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `LimitOffsetClause<diesel::query_builder::limit_clause::NoLimitClause, diesel::query_builder::offset_clause::NoOffsetClause>: IntoBoxedClause<'_, multi_connection_impl::backend::MultiBackend>` is not satisfied
  --> src/main.rs:24:26
   |
24 |     let u = users::table.into_boxed().load::<(i32, String)>(conn);
   |                          ^^^^^^^^^^ the trait `IntoBoxedClause<'_, multi_connection_impl::backend::MultiBackend>` is not implemented for `LimitOffsetClause<diesel::query_builder::limit_clause::NoLimitClause, diesel::query_builder::offset_clause::NoOffsetClause>`
   |
   = help: the trait `IntoBoxedClause<'a, Sqlite>` is implemented for `LimitOffsetClause<diesel::query_builder::limit_clause::NoLimitClause, diesel::query_builder::offset_clause::NoOffsetClause>`
   = note: required for `SelectStatement<FromClause<users::table>>` to implement `BoxedDsl<'_, multi_connection_impl::backend::MultiBackend>`

error[E0277]: the trait bound `LimitOffsetClause<diesel::query_builder::limit_clause::NoLimitClause, diesel::query_builder::offset_clause::NoOffsetClause>: IntoBoxedClause<'_, multi_connection_impl::backend::MultiBackend>` is not satisfied
    --> src/main.rs:24:26
     |
24   |     let u = users::table.into_boxed().load::<(i32, String)>(conn);
     |                          ^^^^^^^^^^ the trait `IntoBoxedClause<'_, multi_connection_impl::backend::MultiBackend>` is not implemented for `LimitOffsetClause<diesel::query_builder::limit_clause::NoLimitClause, diesel::query_builder::offset_clause::NoOffsetClause>`
     |
     = help: the trait `IntoBoxedClause<'a, Sqlite>` is implemented for `LimitOffsetClause<diesel::query_builder::limit_clause::NoLimitClause, diesel::query_builder::offset_clause::NoOffsetClause>`
     = note: required for `SelectStatement<FromClause<users::table>>` to implement `BoxedDsl<'_, multi_connection_impl::backend::MultiBackend>`
     = note: 1 redundant requirement hidden
     = note: required for `users::table` to implement `BoxedDsl<'_, multi_connection_impl::backend::MultiBackend>`
note: required by a bound in `diesel::QueryDsl::into_boxed`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/query_dsl/mod.rs:1299:15
     |
1299 |         Self: methods::BoxedDsl<'a, DB>,
     |               ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `QueryDsl::into_boxed`

error[E0277]: the trait bound `SelectBy<User, multi_connection_impl::backend::MultiBackend>: QueryFragment<Sqlite>` is not satisfied
    --> src/main.rs:28:15
     |
28   |         .load(conn);
     |          ---- ^^^^ the trait `QueryFragment<Sqlite>` is not implemented for `SelectBy<User, multi_connection_impl::backend::MultiBackend>`
     |          |
     |          required by a bound introduced by this call
     |
     = help: the trait `QueryFragment<DB>` is implemented for `SelectBy<T, DB>`
     = note: required for `diesel::query_builder::select_clause::SelectClause<SelectBy<User, multi_connection_impl::backend::MultiBackend>>` to implement `QueryFragment<Sqlite>`
     = note: 4 redundant requirements hidden
     = note: required for `SelectStatement<FromClause<table>, SelectClause<SelectBy<User, MultiBackend>>>` to implement `QueryFragment<multi_connection_impl::backend::MultiBackend>`
     = note: the full type name has been written to '/tmp/diesel_test/target/debug/deps/diesel_test-e9839cd4beffff40.long-type-13019818345722010715.txt'
     = note: required for `SelectStatement<FromClause<table>, SelectClause<SelectBy<User, MultiBackend>>>` to implement `LoadQuery<'_, DbConnection, User>`
     = note: the full type name has been written to '/tmp/diesel_test/target/debug/deps/diesel_test-e9839cd4beffff40.long-type-13019818345722010715.txt'
note: required by a bound in `diesel::RunQueryDsl::load`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/query_dsl/mod.rs:1543:15
     |
1543 |         Self: LoadQuery<'query, Conn, U>,
     |               ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`

error[E0277]: the trait bound `SelectBy<User, multi_connection_impl::backend::MultiBackend>: QueryFragment<Pg>` is not satisfied
    --> src/main.rs:28:15
     |
28   |         .load(conn);
     |          ---- ^^^^ the trait `QueryFragment<Pg>` is not implemented for `SelectBy<User, multi_connection_impl::backend::MultiBackend>`
     |          |
     |          required by a bound introduced by this call
     |
     = help: the trait `QueryFragment<DB>` is implemented for `SelectBy<T, DB>`
     = note: required for `diesel::query_builder::select_clause::SelectClause<SelectBy<User, multi_connection_impl::backend::MultiBackend>>` to implement `QueryFragment<Pg>`
     = note: 4 redundant requirements hidden
     = note: required for `SelectStatement<FromClause<table>, SelectClause<SelectBy<User, MultiBackend>>>` to implement `QueryFragment<multi_connection_impl::backend::MultiBackend>`
     = note: the full type name has been written to '/tmp/diesel_test/target/debug/deps/diesel_test-e9839cd4beffff40.long-type-13019818345722010715.txt'
     = note: required for `SelectStatement<FromClause<table>, SelectClause<SelectBy<User, MultiBackend>>>` to implement `LoadQuery<'_, DbConnection, User>`
     = note: the full type name has been written to '/tmp/diesel_test/target/debug/deps/diesel_test-e9839cd4beffff40.long-type-13019818345722010715.txt'
note: required by a bound in `diesel::RunQueryDsl::load`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/query_dsl/mod.rs:1543:15
     |
1543 |         Self: LoadQuery<'query, Conn, U>,
     |               ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`

(That sounds that some queryfragment impls in diesel are to restrictive for using selectable and/or boxed queries with the new MultiConnection derive.

Are you seeing any additional errors?

Checklist

  • This issue can be reproduced on Rust's stable channel. (Your issue will be
    closed if this is not the case)
  • This issue can be reproduced without requiring a third party crate
@weiznich weiznich added bug hole in api internal or unreleased api Release Blocker This issue needs to be solved before we can release a new version, it can't be punted to the next labels Mar 25, 2023
@weiznich
Copy link
Member Author

I did some work on this and it seems like that the problem with SelectBy is rather easy to solve by introducing the following trait:

    pub trait CompatibleBackend<DB>: Backend {}
    impl<DB> CompatibleBackend<DB> for DB where DB: Backend {}

then we can provide the corresponding additional impl for the generated multibackend type and restrict the QueryFragment impl for SelectBy on that.

Unfortunately that will not work for the boxed select statement case, due to the fact that a boxed select statement internally stores boxed query fragment trait objects for a specific backend type and we cannot simply convert them to something else. At that point I'm not even sure if that ever can be supported :(

weiznich added a commit to weiznich/diesel that referenced this issue Apr 21, 2023
This commit fixes various issues with backend dependent `QueryFragment`
impls in combination with `#[derive(Multiconnection)]`. In all cases we
solve these issues by not calling the concrete backend specific
`QueryFragment` impl early in the query building process. Instead we
call the generic `MultiBackend` specific impl, that later defer to the
correct implementation specific one. In addition this commit adds some
test for the fixed cases.
weiznich added a commit to weiznich/diesel that referenced this issue Apr 21, 2023
This commit fixes various issues with backend dependent `QueryFragment`
impls in combination with `#[derive(Multiconnection)]`. In all cases we
solve these issues by not calling the concrete backend specific
`QueryFragment` impl early in the query building process. Instead we
call the generic `MultiBackend` specific impl, that later defer to the
correct implementation specific one. In addition this commit adds some
test for the fixed cases.
weiznich added a commit to weiznich/diesel that referenced this issue Apr 24, 2023
This commit fixes various issues with backend dependent `QueryFragment`
impls in combination with `#[derive(Multiconnection)]`. In all cases we
solve these issues by not calling the concrete backend specific
`QueryFragment` impl early in the query building process. Instead we
call the generic `MultiBackend` specific impl, that later defer to the
correct implementation specific one. In addition this commit adds some
test for the fixed cases.
weiznich added a commit to weiznich/diesel that referenced this issue Apr 24, 2023
This commit fixes various issues with backend dependent `QueryFragment`
impls in combination with `#[derive(Multiconnection)]`. In all cases we
solve these issues by not calling the concrete backend specific
`QueryFragment` impl early in the query building process. Instead we
call the generic `MultiBackend` specific impl, that later defer to the
correct implementation specific one. In addition this commit adds some
test for the fixed cases.
weiznich added a commit to weiznich/diesel that referenced this issue Apr 24, 2023
This commit fixes various issues with backend dependent `QueryFragment`
impls in combination with `#[derive(Multiconnection)]`. In all cases we
solve these issues by not calling the concrete backend specific
`QueryFragment` impl early in the query building process. Instead we
call the generic `MultiBackend` specific impl, that later defer to the
correct implementation specific one. In addition this commit adds some
test for the fixed cases.
weiznich added a commit to weiznich/diesel that referenced this issue Apr 24, 2023
This commit fixes various issues with backend dependent `QueryFragment`
impls in combination with `#[derive(Multiconnection)]`. In all cases we
solve these issues by not calling the concrete backend specific
`QueryFragment` impl early in the query building process. Instead we
call the generic `MultiBackend` specific impl, that later defer to the
correct implementation specific one. In addition this commit adds some
test for the fixed cases.
weiznich added a commit to weiznich/diesel that referenced this issue Apr 24, 2023
This commit fixes various issues with backend dependent `QueryFragment`
impls in combination with `#[derive(Multiconnection)]`. In all cases we
solve these issues by not calling the concrete backend specific
`QueryFragment` impl early in the query building process. Instead we
call the generic `MultiBackend` specific impl, that later defer to the
correct implementation specific one. In addition this commit adds some
test for the fixed cases.
weiznich added a commit to weiznich/diesel that referenced this issue Apr 24, 2023
This commit fixes various issues with backend dependent `QueryFragment`
impls in combination with `#[derive(Multiconnection)]`. In all cases we
solve these issues by not calling the concrete backend specific
`QueryFragment` impl early in the query building process. Instead we
call the generic `MultiBackend` specific impl, that later defer to the
correct implementation specific one. In addition this commit adds some
test for the fixed cases.

Acked-by: Georg Semmler <github@weiznich.de>
weiznich added a commit to weiznich/diesel that referenced this issue Apr 24, 2023
This commit fixes various issues with backend dependent `QueryFragment`
impls in combination with `#[derive(Multiconnection)]`. In all cases we
solve these issues by not calling the concrete backend specific
`QueryFragment` impl early in the query building process. Instead we
call the generic `MultiBackend` specific impl, that later defer to the
correct implementation specific one. In addition this commit adds some
test for the fixed cases.

Acked-by: Georg Semmler <github@weiznich.de>
weiznich added a commit that referenced this issue Apr 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug hole in api internal or unreleased api Release Blocker This issue needs to be solved before we can release a new version, it can't be punted to the next
Projects
None yet
Development

No branches or pull requests

1 participant