Search code examples
postgresqlrustrust-sqlx

How to represent array of strings column in Rust sqlx


I have a table called product; one of the columns called tags is JSONB type and essentially contains an array of strings. Each product in the table has various amounts of tags. Some can be 0 some can be 40. I've created a struct in Rust to best represent the table structure and I have some conflicts with the sqlx JSON types for that column. The structs are:

#[derive(Deserialize)]
pub struct Product {
    pub id: i32,
    pub product_id: i64,
    pub title: String,
    pub handle: Option<String>,
    pub tags: Vec<String>,
    pub product_type: Option<String>,
    pub image_url: String,
    pub created_at: String,
    pub updatedAt: String,
}

#[derive(Deserialize)]
pub struct ProductPatch {
    pub product_id: i64,
    pub title: String,
    pub handle: Option<String>,
    pub tags: Vec<String>,
    pub product_type: Option<String>,
    pub image_url: String,
}

And my add_product function using that struct:

async fn add_product(
    pool: &Db,
    product: ProductPatch,
) -> Result<ProductPatch, sqlx::postgres::PgDatabaseError> {
    let rec = sqlx::query_as!(
        ProductPatch,
        r#"--sql
        INSERT INTO products (product_id, title, handle, tags, product_type, image_url)
        VALUES ($1, $2, $3, $4, $5, $6)
        RETURNING product_id, title, handle, tags, product_type, image_url
        "#,
        &product.product_id,
        &product.title,
        &product.handle.unwrap(),
        &product.tags,
        &product.product_type.unwrap(),
        &product.image_url
    )
    .fetch_one(&pool.clone())
    .await;

    Ok(rec.unwrap())
}

The error I'm dealing with is

expected struct Vec<std::string::String> found enum std::option::Option<JsonValue>rustcE0308

Should I be creating an enum for that specific column and referencing that in my struct? That doesn't feel right since it's just an array of strings.


Solution

  • I had the same issue. You actually need to pass the Vec<String> serialized as String e.g. with serde_json::to_string(&product.tags) in the query.