-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Implementation of sqlx::Acquire
is not general enough for MySqlConnection
#1015
Comments
sqlx::Acquire
is not general enoughsqlx::Acquire
is not general enough for MySqlConnection
Related to #954 but this seems to concern a different trait impl, or at least one of the errors does. |
Thank you for classifying this. I see you added |
I don't think this is related to #954, and probably a bug in user code. Can you provide a minimal verifiable example? |
Also, what version of Rust are you using? |
My first post contains all the code required to reproduce the issue. Bug was present with both Rust
Do you any need any more information? |
Interesting, it works if you remove just the attributes. Also, I've been able to reduce this using use rocket::{data::Data, handler::HandlerFuture, request::Request, State};
use sqlx::{Acquire, MySql, Pool};
#[allow(unreachable_code)]
fn monomorphized_function<'_b>(__req: &'_b Request, __data: Data) -> HandlerFuture<'_b> {
Box::pin(async move {
let __rocket_param_pool: State<'_, Pool<MySql>> = todo!();
let ___responder = pool(__rocket_param_pool).await;
rocket::handler::Outcome::from(__req, ___responder)
})
}
async fn pool(pool: State<'_, Pool<MySql>>) {
run_query(&*pool).await;
}
async fn run_query<'c, E>(pool: E)
where
E: Acquire<'c, Database = MySql>,
{
let mut conn = pool.acquire().await.unwrap();
sqlx::query("SELECT 1").fetch_one(&mut *conn).await.unwrap();
} The reason I find this very weird is that rustc complains about the bound in |
This seems to come down to lifetime parameters spilling into |
Okay, I was wrong. This is related to fn run_query<'a, 'c, E>(pool: E) -> impl Future<Output = ()> + Send + 'a
where
E: Acquire<'c, Database = MySql> + Send + 'a,
E::Connection: Send,
{
async move {
let mut conn = pool.acquire().await.unwrap();
sqlx::query("SELECT 1").fetch_one(&mut *conn).await.unwrap();
}
} However, that produces a rather unhelpful error message:
I will try to minimize that error and create an issue at rust-lang/rust. I've also found a fix to this! For some reason that I couldn't figure out it only works against the current git master of sqlx, not against 0.4.2: You have to add the diff --git a/sqlx-core/src/acquire.rs b/sqlx-core/src/acquire.rs
index 308e80da..dd8670ae 100644
--- a/sqlx-core/src/acquire.rs
+++ b/sqlx-core/src/acquire.rs
@@ -8,7 +8,7 @@ use std::ops::{Deref, DerefMut};
pub trait Acquire<'c> {
type Database: Database;
- type Connection: Deref<Target = <Self::Database as Database>::Connection> + DerefMut;
+ type Connection: Deref<Target = <Self::Database as Database>::Connection> + DerefMut + Send;
fn acquire(self) -> BoxFuture<'c, Result<Self::Connection, Error>>; and then define fn run_query<'a, 'c, E>(pool: E) -> impl Future<Output = ()> + Send + 'a
where
E: Acquire<'c, Database = MySql> + Send + 'a,
{
async move {
let mut conn = pool.acquire().await.unwrap();
sqlx::query("SELECT 1").fetch_one(&mut *conn).await.unwrap();
}
} (same as above, but without the bound on Realistically though, I'd recommend just not using the #[macro_use]
extern crate rocket;
use rocket::State;
use sqlx::{MySql, MySqlConnection, Pool};
#[get("/pool")]
async fn pool(pool: State<'_, Pool<MySql>>) {
let mut conn = pool.acquire().await.unwrap();
run_query(&mut conn).await;
}
#[get("/transaction")]
async fn txn(pool: State<'_, Pool<MySql>>) {
let mut txn = pool.begin().await.unwrap();
run_query(&mut *txn).await;
txn.commit().await.unwrap();
}
async fn run_query(conn: &mut MySqlConnection) {
sqlx::query("SELECT 1").fetch_one(conn).await.unwrap();
} |
Using I don't know if you wish to keep this open or not (if there is actually an issue, regardless of my particular problem). I'll leave the decision to you. Have a nice day. |
This is, for me, a weird one, that I can only reproduce in a very specific situation, which may or may not be on
sqlx
's side.My setup includes version
0.4.2
of sqlx, with Rocket frommaster
(more on that below).I am using
sqlx
as aState
in Rocket, so I can recover aPool<MySql>
in every action function. The global idea of what I am trying to do is create database-layer functions that could either directly take&Pool<MySql>
s or transactions into the pool (depending on where it is used, it may or may not be part of a transaction).When used this way,, an error saying that the
implementation of sqlx::Acquire is not general enough
.Here is a full minimal reproduction of the issue:
The reported error is the following:
The exact same function works properly when used without the Rocket layer, but fails when wrapped in Rocket's macros. I reported the issue here first because the error mentioned
sqlx::Acquire
. But I really have no idea what is going on.Feel free to close if you think this is a Rocket issue (and sorry if it is).
Thank you.
The text was updated successfully, but these errors were encountered: