Building a dynamic query in SQLx with `optional_field::Field`

āš“ Rust    šŸ“… 2026-06-10    šŸ‘¤ surdeus    šŸ‘ļø 3      

surdeus

I’m struggling to create a heterogeneous Vec containing instances of optional_field::Field for use with SQLx:

trait FieldValue<'a>: sqlx::Encode<'a, Sqlite> + sqlx::Type<Sqlite> {}

fn build_update<'a, T: FromRow<'a, SqliteRow>>(
    table: &'static str,
    id: RawIdType,
    fields: Vec<(&'static str, Field<Box<dyn FieldValue<'a>>>)>,
) -> QueryAs<'a, Sqlite, T, SqliteArguments> {
    let mut query: QueryBuilder<Sqlite> = QueryBuilder::new(format!("UPDATE {table} SET "));

    {
        let mut separated = query.separated(", ");

        for (name, field) in fields {
            add_field(name, field, &mut separated);
        }
    }

    constrain_update(id, &mut query);
    query.build_query_as()
}

pub fn add_field<'a, T>(
    name: &str,
    field: Field<Box<T>>,
    query: &mut sqlx::query_builder::Separated<Sqlite, &str>,
) where
    T: sqlx::Type<Sqlite> + sqlx::Encode<'a, Sqlite>,
{
    match field {
        Field::Present(Some(val)) => {
            query.push(name);
            query.push_unseparated(" = ");
            query.push_bind_unseparated(*val);
        }
        Field::Present(None) => {
            query.push(name);
            query.push_unseparated(" = ");
            query.push_unseparated("NULL");
        }
        _ => {}
    }
}

pub fn constrain_update(id: RawIdType, query: &mut QueryBuilder<Sqlite>) {
  // omitted
}

I created that FieldValue trait based on a compiler error about auto traits but now I get:

error[E0038]: the trait `FieldValue` is not dyn compatible
   --> crates\server\src\db.rs:73:42
    |
 73 |     fields: Vec<(&'static str, Field<Box<dyn FieldValue<'a>>>)>,
    |                                          ^^^^^^^^^^^^^^^^^^ `FieldValue` is not dyn compatible
    |
note: for a trait to be dyn compatible it needs to allow building a vtable
      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> C:\Users\A\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\sqlx-core-0.9.0\src\types\mod.rs:219:8

Is there a way I can phrase this to satisfy the compiler?

1 post - 1 participant

Read full topic

šŸ·ļø Rust_feed