`sqlx::query_*` not working when imported from `rocket_db_pools`
Description
I want to use the sqlx::query_* macros as demonstrated in your database example but with Postgres instead of Sqlite. However, when I tried to adapt the example to my use case:
// src/models.rs
use rocket::form::FromForm;
use rocket::serde::{Deserialize, Serialize};
use rocket_db_pools::{sqlx, sqlx::Row, Connection};
use crate::db::Db;
#[derive(Debug, FromForm, Clone, Deserialize, Serialize)]
#[serde(crate = "rocket::serde")]
pub struct NewClient<'v> {
#[field(validate = len(1..).or_else(msg!("Enter the client's first name")))]
pub first_name: &'v str,
#[field(validate = len(1..).or_else(msg!("Enter the client's last name")))]
pub last_name: &'v str,
#[field(validate = contains('@').or_else(msg!("Enter a valid email address")))]
pub email_address: &'v str,
pub telephone_number: &'v str,
}
pub struct NewClientId{
id: i64
}
impl NewClient<'_> {
pub async fn add(&self, mut db: Connection<Db>) -> Result<i64, sqlx::Error> {
let new_client_id = sqlx::query_file_as!(
NewClientId,
"queries/add_client.sql",
self.first_name,
self.last_name,
self.email_address,
self.telephone_number
)
.fetch_one(&mut *db)
.await?;
Ok(new_client_id.id)
}
}
I got the following error message:
error[E0034]: multiple applicable items in scope
--> src/models.rs:25:29
|
25 | let new_client_id = sqlx::query_file_as!(
| _____________________________^
26 | | NewClientId,
27 | | "queries/add_client.sql",
28 | | self.first_name,
... |
31 | | self.telephone_number
32 | | )
| |_________^ multiple `default` found
|
note: candidate #1 is defined in the trait `std::default::Default`
--> /home/ed/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/default.rs:133:5
|
133 | fn default() -> Self;
| ^^^^^^^^^^^^^^^^^^^^^
note: candidate #2 is defined in the trait `FromForm`
--> /home/ed/.cargo/registry/src/github.com-1ecc6299db9ec823/rocket-0.5.0-rc.2/src/form/from_form.rs:551:5
|
551 | fn default(opts: Options) -> Option<Self> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` (in Nightly builds, run with -Z macro-backtrace for more info)
help: disambiguate the associated function for candidate #1
|
598 | <_ as std::default::Default>::$crate::sqlx_macros::expand_query!(record = $out_struct, source_file = $path, args = [$($args)*])
| ++++++++++++++++++++++++++++++
help: disambiguate the associated function for candidate #2
|
598 | <_ as FromForm>::$crate::sqlx_macros::expand_query!(record = $out_struct, source_file = $path, args = [$($args)*])
| +++++++++++++++++
error[E0277]: the trait bound `rocket_db_pools::sqlx::Postgres: sqlx::database::HasArguments<'_>` is not satisfied
--> src/models.rs:25:29
|
25 | let new_client_id = sqlx::query_file_as!(
| _____________________________^
26 | | NewClientId,
27 | | "queries/add_client.sql",
28 | | self.first_name,
... |
31 | | self.telephone_number
32 | | )
| |_________^ the trait `sqlx::database::HasArguments<'_>` is not implemented for `rocket_db_pools::sqlx::Postgres`
|
= help: the trait `sqlx::database::HasArguments<'_>` is implemented for `sqlx::Postgres`
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `rocket_db_pools::sqlx::Postgres: sqlx::Database` is not satisfied
--> src/models.rs:25:29
|
25 | let new_client_id = sqlx::query_file_as!(
| _____________________________^
26 | | NewClientId,
27 | | "queries/add_client.sql",
28 | | self.first_name,
... |
31 | | self.telephone_number
32 | | )
| |_________^ the trait `sqlx::Database` is not implemented for `rocket_db_pools::sqlx::Postgres`
|
= help: the trait `sqlx::Database` is implemented for `sqlx::Postgres`
note: required by a bound in `sqlx::Encode::size_hint`
--> /home/ed/.cargo/registry/src/github.com-1ecc6299db9ec823/sqlx-core-0.6.0/src/encode.rs:19:26
|
19 | pub trait Encode<'q, DB: Database> {
| ^^^^^^^^ required by this bound in `sqlx::Encode::size_hint`
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> src/models.rs:25:29
|
25 | let new_client_id = sqlx::query_file_as!(
| _____________________________^
26 | | NewClientId,
27 | | "queries/add_client.sql",
28 | | self.first_name,
... |
31 | | self.telephone_number
32 | | )
| |_________^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
= help: the following other types implement trait `sqlx::Encode<'q, DB>`:
&str
std::string::String
= note: required because of the requirements on the impl of `sqlx::Encode<'_, rocket_db_pools::sqlx::Postgres>` for `&str`
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `str: sqlx::Encode<'_, rocket_db_pools::sqlx::Postgres>` is not satisfied
--> src/models.rs:25:29
|
25 | let new_client_id = sqlx::query_file_as!(
| _____________________________^
26 | | NewClientId,
27 | | "queries/add_client.sql",
28 | | self.first_name,
... |
31 | | self.telephone_number
32 | | )
| |_________^ the trait `sqlx::Encode<'_, rocket_db_pools::sqlx::Postgres>` is not implemented for `str`
|
= help: the following other types implement trait `sqlx::Encode<'q, DB>`:
&str
std::string::String
= note: required because of the requirements on the impl of `sqlx::Encode<'_, rocket_db_pools::sqlx::Postgres>` for `&str`
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0599]: the method `try_map` exists for struct `sqlx::query::Query<'_, rocket_db_pools::sqlx::Postgres, _>`, but its trait bounds were not satisfied
--> src/models.rs:25:29
|
25 | let new_client_id = sqlx::query_file_as!(
| _____________________________^
26 | | NewClientId,
27 | | "queries/add_client.sql",
28 | | self.first_name,
... |
31 | | self.telephone_number
32 | | )
| |_________^ method cannot be called on `sqlx::query::Query<'_, rocket_db_pools::sqlx::Postgres, _>` due to unsatisfied trait bounds
|
::: /home/ed/.cargo/registry/src/github.com-1ecc6299db9ec823/sqlx-core-0.5.13/src/postgres/database.rs:11:1
|
11 | pub struct Postgres;
| -------------------- doesn't satisfy `rocket_db_pools::sqlx::Postgres: sqlx::Database`
|
= note: the following trait bounds were not satisfied:
`rocket_db_pools::sqlx::Postgres: sqlx::Database`
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` (in Nightly builds, run with -Z macro-backtrace for more info)
Now, obviously, I could have made a mistake when adapting, but the code works fine if I import sqlx::query_* macros from sqlx instead.
// src/models.rs
use rocket::form::FromForm;
use rocket::serde::{Deserialize, Serialize};
use sqlx::{self, postgres::PgPool};
#[derive(Debug, FromForm, Clone, Deserialize, Serialize)]
#[serde(crate = "rocket::serde")]
pub struct NewClient<'v> {
#[field(validate = len(1..).or_else(msg!("Enter the client's first name")))]
pub first_name: &'v str,
#[field(validate = len(1..).or_else(msg!("Enter the client's last name")))]
pub last_name: &'v str,
#[field(validate = contains('@').or_else(msg!("Enter a valid email address")))]
pub email_address: &'v str,
pub telephone_number: &'v str,
}
pub struct NewClientId{
id: i64
}
impl NewClient<'_> {
pub async fn add(&self, pool: &PgPool) -> Result<i64, sqlx::Error> {
let new_client_id = sqlx::query_file_as!(
NewClientId,
"queries/add_client.sql",
self.first_name,
self.last_name,
self.email_address,
self.telephone_number
)
.fetch_one(pool)
.await?;
Ok(new_client_id.id)
}
}
This wouldn't be so bad if I could still use the launch pattern in the example, but instead I need to manage the Postgres db as demonstrated in this gist.
To Reproduce
// src/db.rs
use rocket_db_pools::Database;
use rocket_db_pools::sqlx::PgPool;
#[derive(Database)]
#[database("rust-backend")]
pub struct Db(PgPool);
-- queries/add_client.sql
INSERT INTO clients (first_name, last_name, email_address, telephone_number) VALUES ($1, $2, $3, $4) RETURNING id;
Expected Behavior
sqlx::query_* macros imported from rocket_db_pools will work if their sqlx equivalents will.
Environment:
- OS Distribution and Kernel: KDE neon User - 5.25
- Rocket Version: 0.5.0-rc.2
Can you check what version of sqlx you're using? I would assume that the macros re-exported from Rocket may be from a different version of sqlx.
Otherwise, it's quite possible that the re-export is messing with the $crate value in the macros. It's been a hot minute since I've worked with these kinds of macros, so I'm probably missing something.
I'm using:
sqlx = { version = "0.6.0", features = ["macros", "runtime-tokio-rustls", "postgres", "uuid", "chrono", "migrate", "offline"] }
It looks like rocket_db_pools depends on 0.5. Does downgrading to 0.5.0 break it?
You may be best off setting the version to *, since it should then select the version rocket depends on.
No, it compiles with sqlx set to 0.5.0 or *. It's using the sqlx macros from rocket_db_pools that's the problem.
yeah they will probably never work, you need sqlx as dependency
No, it compiles with
sqlxset to0.5.0or*. It's using thesqlxmacros fromrocket_db_poolsthat's the problem.
This is just a version mismatch. You need to be using the same version as rocket_db_pools uses.