Diesel: Can't deserialize structs with Option<BigDecimal>

Created on 11 Oct 2018  Â·  5Comments  Â·  Source: diesel-rs/diesel

Setup

Versions

  • Rust:
$ rustc --version
rustc 1.29.1 (b801ae664 2018-09-20)
  • Diesel: 1.3.3
  • Database: postgres
  • Operating System OS X

Feature Flags

  • diesel: diesel = { version = "1.0.0", features = ["postgres", "32-column-tables", "numeric"] }

Problem Description

My table! definition has Numeric and Nullable<Numeric> value. I can represent BigDecimal in a struct but not Option<BigDecimal>. I get the following error:

error[E0277]: the trait bound `std::option::Option<bigdecimal::BigDecimal>: diesel::Queryable<diesel::sql_types::Numeric, diesel::pg::Pg>` is not satisfied
  --> src/main.rs:87:40
   |
87 |     let res = purchase_orders.limit(1).load::<PurchaseOrder>(&conn).unwrap();
   |                                        ^^^^ the trait `diesel::Queryable<diesel::sql_types::Numeric, diesel::pg::Pg>` is not implemented for `std::option::Option<bigdecimal::BigDecimal>`
   |
   = help: the following implementations were found:
             <std::option::Option<T> as diesel::Queryable<diesel::sql_types::Nullable<ST>, DB>>
   = note: required because of the requirements on the impl of `diesel::Queryable<(diesel::sql_types::Integer, diesel::sql_types::Nullable<diesel::sql_types::Text>, diesel::sql_types::Nullable<diesel::sql_types::Integer>, diesel::sql_types::Nullable<diesel::sql_types::Text>, diesel::sql_types::Nullable<diesel::sql_types::Timestamp>, diesel::sql_types::Integer, diesel::sql_types::Nullable<diesel::sql_types::Bool>, diesel::sql_types::Nullable<diesel::sql_types::Bool>, diesel::sql_types::Nullable<diesel::sql_types::Bool>, diesel::sql_types::Nullable<diesel::sql_types::Bool>, diesel::sql_types::Nullable<diesel::sql_types::Numeric>, diesel::sql_types::Numeric, diesel::sql_types::Numeric, diesel::sql_types::Numeric), diesel::pg::Pg>` for `(i32, std::option::Option<std::string::String>, std::option::Option<i32>, std::option::Option<std::string::String>, std::option::Option<std::time::SystemTime>, i32, std::option::Option<bool>, std::option::Option<bool>, std::option::Option<bool>, std::option::Option<bool>, bigdecimal::BigDecimal, bigdecimal::BigDecimal, bigdecimal::BigDecimal, std::option::Option<bigdecimal::BigDecimal>)`
   = note: required because of the requirements on the impl of `diesel::Queryable<(diesel::sql_types::Integer, diesel::sql_types::Nullable<diesel::sql_types::Text>, diesel::sql_types::Nullable<diesel::sql_types::Integer>, diesel::sql_types::Nullable<diesel::sql_types::Text>, diesel::sql_types::Nullable<diesel::sql_types::Timestamp>, diesel::sql_types::Integer, diesel::sql_types::Nullable<diesel::sql_types::Bool>, diesel::sql_types::Nullable<diesel::sql_types::Bool>, diesel::sql_types::Nullable<diesel::sql_types::Bool>, diesel::sql_types::Nullable<diesel::sql_types::Bool>, diesel::sql_types::Nullable<diesel::sql_types::Numeric>, diesel::sql_types::Numeric, diesel::sql_types::Numeric, diesel::sql_types::Numeric), diesel::pg::Pg>` for `scientist::models::purchase_order::PurchaseOrder`
   = note: required because of the requirements on the impl of `diesel::query_dsl::LoadQuery<_, scientist::models::purchase_order::PurchaseOrder>` for `diesel::query_builder::SelectStatement<scientist::tables::purchase_orders_tl::purchase_orders::table, diesel::query_builder::select_clause::DefaultSelectClause, diesel::query_builder::distinct_clause::NoDistinctClause, diesel::query_builder::where_clause::NoWhereClause, diesel::query_builder::order_clause::NoOrderClause, diesel::query_builder::limit_clause::LimitClause<diesel::expression::bound::Bound<diesel::sql_types::BigInt, i64>>>`

What are you trying to accomplish?

I want to support Option<Numeric> values.

What is the expected output?

It should compile and deserialize the same as Option<bool> and friends.

What is the actual output?

Are you seeing any additional errors?

Steps to reproduce

table! {
    purchase_orders (id) {
        id -> Int4,
        commission_rate -> Nullable<Numeric>,
   }
}
#[derive(Queryable, Debug)]
pub struct PurchaseOrder {
    id: i32,
    commission_rate: Option<BigDecimal>
}
fn do_postgresy_stuff(args: Args) -> Result<(),diesel::ConnectionError> {
    let conn = PgConnection::establish(&args.arg_POSTGRES_URI)?;

//    let res = proposals.limit(100).offset(600).filter(provider_id.is_not_null()).load::<Proposal>(&conn).unwrap();
    let res = purchase_orders.limit(1).load::<PurchaseOrder>(&conn).unwrap();
    println!("res: {:#?}", res);

    Ok(())
}

Checklist

  • [*] I have already looked over the issue tracker for similar issues.
  • [*] This issue can be reproduced on Rust's stable channel. (Your issue will be
    closed if this is not the case)

Most helpful comment

In case anyone else misses this: you'll need to set the serde feature on bigdecimal for all of this to work.

All 5 comments

@xrl: which version of BigDecimal do you depend on?

I think I've had that error when I've used two different versions of BigDecimal. The current stable release series 1.3.X depends on bigdecimal = { version = ">= 0.0.10, < 0.0.12", optional = true }.
(Support for the most recent version of bigdecimal has been added to the 1.4 milestone: https://github.com/diesel-rs/diesel/pull/1837)

@kestred I did hit that problem initial, now I've made sure to sync up the library versions. the error still happens when versions are synced:

$ cargo tree | grep bigdecimal
├── bigdecimal v0.0.11
│   ├── bigdecimal v0.0.11 (*)

OK, turns out my reproduction wasn't fair. Looks like the ordering of properties in the target struct must match the order in the table! definition. Whoops 😦

Closing!

In case anyone else misses this: you'll need to set the serde feature on bigdecimal for all of this to work.

Thanks @inferiorhumanorgans, config below fixed my problem

[dependencies.bigdecimal]
version = "0.1.0"
features = ["serde"]

[dependencies.diesel]
version = "1.4.4"
features = ["numeric"]
Was this page helpful?
0 / 5 - 0 ratings