I am trying to load an array field in Postgres to a Rust struct as follows
use sqlx::{Pool, PgConnection, PgPool, FromRow};
use sqlx::postgres::PgQueryAs;
#[derive(Copy, Clone, sqlx::Type)]
#[sqlx(rename = "VARCHAR")]
#[sqlx(rename_all = "snake_case")]
enum Coupon {
ChristmasSaleCoupon,
NewYearSaleCoupon,
}
#[derive(FromRow, Clone)]
struct UserCouponMap {
pub id: i64,
pub user_id: i64,
pub coupons: Vec<Coupon>,
}
impl UserCouponMap {
pub async fn get_for_userid(db_pool: Pool<PgConnection>, user_id: i64) -> Vec<UserCouponMap> {
let user_coupon_map: Vec<UserCouponMap> = sqlx::query_as("SELECT * FROM user_coupon_map WHERE user_id = $1")
.bind(user_id)
.fetch_all(db_pool)
.await
.expect("failed to fetch user coupon map");
user_coupon_map
}
}
#[tokio::main]
async fn fetch_coupons_for_user_id(user_id: i64) {
let pool = PgPool::new("postgresql://asnim@dbhost:5732").await.expect("expected unwrap to succeed");
let user_coupon_map = UserCouponMap::get_for_userid(pool, user_id).await;
}
fn main() {
fetch_coupons_for_user_id(20);
}
As per the Array documentation, I have implemented sqlx::Type
for Coupon
.
Still, the compiler says, some trait is not satisfied.
Compiling playground v0.1.0 (/Users/asnimansari/CLionProjects/playground)
error[E0277]: the trait bound `Vec<Coupon>: Type<Postgres>` is not satisfied
--> src/main.rs:23:14
|
23 | .fetch_all(db_pool)
| ^^^^^^^^^ the trait `Type<Postgres>` is not implemented for `Vec<Coupon>`
|
= help: the following implementations were found:
<Vec<&[u8]> as Type<Postgres>>
<Vec<&str> as Type<Postgres>>
<Vec<(T1, T2)> as Type<Postgres>>
<Vec<(T1, T2, T3)> as Type<Postgres>>
and 29 others
= note: required because of the requirements on the impl of `for<'c> FromRow<'c, PgRow<'c>>` for `UserCouponMap`
error[E0277]: the trait bound `[Coupon]: Type<Postgres>` is not satisfied
--> src/main.rs:23:14
|
23 | .fetch_all(db_pool)
| ^^^^^^^^^ the trait `Type<Postgres>` is not implemented for `[Coupon]`
|
= help: the following implementations were found:
<[&[u8]] as Type<Postgres>>
<[&str] as Type<Postgres>>
<[(T1, T2)] as Type<Postgres>>
<[(T1, T2, T3)] as Type<Postgres>>
and 29 others
= note: required because of the requirements on the impl of `sqlx::decode::Decode<'_, Postgres>` for `Vec<Coupon>`
= note: required because of the requirements on the impl of `for<'c> FromRow<'c, PgRow<'c>>` for `UserCouponMap`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground`
To learn more, run the command again with --verbose.
What am I missing here?
My Cargo file has the following dependencies
sqlx = { version = "0.3.5", default-features = false, features = ["runtime-tokio", "macros", "postgres", "all-type"] }
tokio = { version = "0.2.21", features = ["full"] }
One way it should work is to use explicit column list and declare rust type in the query. For OP case:
let user_coupon_map: Vec<UserCouponMap> = sqlx::query_as!(r#"SELECT id, user_id, coupons as "coupons: Vec<Coupon>" FROM user_coupon_map WHERE user_id = $1"#)...
It may not cover all your needs. If you use query builder like sea_query, then it won't do.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With