sqlx icon indicating copy to clipboard operation
sqlx copied to clipboard

Macros don't seem to work with AnyPool

Open DarrienG opened this issue 4 years ago • 14 comments

Instantiate yourself an AnyPool (in my case with a Sqlite connection),

pub async fn init_data_pool() -> Result<AnyPool, io::Error> {
    Ok(AnyPoolOptions::new()
        .max_connections(10)
        .connect("sqlite://dev.sqlite3")
        .await
        .map_err(|e| {
            error!("Encountered error trying to make database pool: {}", e);
            Error::new(io::ErrorKind::ConnectionAborted, e)
        })?)
}

Now you have your pool, but it's really an AnyPool.

Let's give it a query:

#[some_async_main]
async fn main() -> io::Result<()> {
    let pool = init_data_pool().await?;
    give_me_data(pool.clone()).await;
}

struct SomeResult {
    id: i64,
    data: i64,
}

async fn give_me_data(pool: AnyPool) {
    // this works as expected
    sqlx::query("SELECT id, data FROM some_table")
        .fetch(&pool).await.unwrap();

    // this throws a compile error
    sqlx::query!("SELECT id, data FROM some_table")
        .fetch(&pool).await.unwrap();    
}

The first query behaves as expected. The second one throws a compile error where sqlx seems to be a little too aware of what the AnyPool really is:

   |
85 |         .fetch(conn);
   |          ^^^^^ expected struct `sqlx::Any`, found struct `sqlx::Sqlite`

I've tried manually getting a connection from the pool, making it a mutable reference, making it not a reference (but also mutable), and it all seems to throw the same compile error. This isn't a problem with the non-macro version of query, so I assume this is a bug.

Supporting info

$ rustc --version                                
rustc 1.49.0 (e1884a8e3 2020-12-29)

sqlx version:

sqlx = { version = "0.4.2", features = ["runtime-actix-rustls", "any", "sqlite", "macros"], default-features = false }

DarrienG avatar Jan 07 '21 02:01 DarrienG

Yeah, the macros emit instances of query::Map that are specifically keyed to the same database they compiled against. I think this is a really important sanity check and I'm loathe to drop it by default.

However, we are discussing a way to configure the macros in #916 and #121, and I think this would be a good configuration option to add, something like use_any_db: bool. @mehcode?

abonander avatar Jan 08 '21 02:01 abonander

Alternatively we could support a protocol like sqlite+anydb:// in database URLs that would cause the macros to emit DB = Any instead of DB = Sqlite where applicable. I'm not sure which I prefer.

abonander avatar Jan 08 '21 03:01 abonander

After discussing on Discord, @mehcode and I decided we'll support both options:

  • sqlx::macros!(driver = "any") which can also be used to enforce, e.g. sqlx::macros!(driver = "postgres") (will error if DATABASE_URL=mysql://..), etc.
  • DATABASE_URL=any+<postgresql | mysql | sqlite | ...>://.., the logic being that any+ is easier to prepend and strip off later than it is to insert and remove +any

abonander avatar Jan 08 '21 03:01 abonander

I didn't expect a response so fast!

Thanks a bunch everyone. I look forward to it being in 0.5 😃

DarrienG avatar Jan 08 '21 04:01 DarrienG

This is a problem we've known about for a while but weren't quite sure how to address. In the context of other ongoing discussions the sqlx::macros!(driver = "any") solution was rather obvious at least.

abonander avatar Jan 08 '21 22:01 abonander

Hi, I've a follow up question related to this issue. I'm writing a web application which should be able to support multiple database backends, one at a time, defined by the user / admin via a configuration file. I thought Any would be the best way to go on the one hand. On the other hand I like the concept of compile time checks done by the query macros. That's why today I crossed the issue described here.

I already experimented with Offline and sqlx-cli. That works like a charm! Anyway I'm wondering if as soon as the query macros allow to use Any I'm good to go or if I rely on a fundamental misunderstanding reaching beyond the ability of query macros to work with Any.

Thanks for your support.

tokcum avatar Jan 20 '21 21:01 tokcum

What is the status on this issue? Doesn't seem like it is in the milestone for next major version.

JohnDowson avatar Oct 20 '21 21:10 JohnDowson

EDIT: sorry, confused the issue with something else.

nitnelave avatar Oct 21 '21 00:10 nitnelave

Is there any status on this? It's been a while.

coredoesdev avatar Oct 12 '22 01:10 coredoesdev

Is there any status on this? It's been a while.

buf1024 avatar Nov 05 '23 03:11 buf1024

Is there any status on this? It's been a while.

I'd just use the "unsafe" version and skip the macro. That's what I ended up doing, and probably better to do than wait another three years.

DarrienG avatar Nov 05 '23 13:11 DarrienG

@DarrienG can you show an example? Thanks!

Is there any status on this? It's been a while.

I'd just use the "unsafe" version and skip the macro. That's what I ended up doing, and probably better to do than wait another three years.

buf1024 avatar Nov 06 '23 06:11 buf1024

@DarrienG can you show an example? Thanks!

Is there any status on this? It's been a while.

I'd just use the "unsafe" version and skip the macro. That's what I ended up doing, and probably better to do than wait another three years.

Look at the issue I wrote 3 years ago. There's an example that works, and one that throws a compile error. The one that works is the "unsafe" one

DarrienG avatar Nov 06 '23 11:11 DarrienG

After discussing on Discord, @mehcode and I decided we'll support both options:

* `sqlx::macros!(driver = "any")` which can also be used to enforce, e.g. `sqlx::macros!(driver = "postgres")` (will error if `DATABASE_URL=mysql://..`), etc.

* `DATABASE_URL=any+<postgresql | mysql | sqlite | ...>://..`, the logic being that `any+` is easier to prepend and strip off later than it is to insert and remove `+any`

Is this still planned?

SolidTux avatar Apr 16 '25 13:04 SolidTux