The trait `diesel::Expression` is not implemented for `chrono::datetime::DateTime<chrono::offset::utc::Utc>`

I have a problem in my code for creating a table in rocket with serde and chrono with datetime
Here is the error :


error[E0277]: the trait bound `chrono::datetime::DateTime<chrono::offset::utc::Utc>: diesel::Expression` is not satisfied
  --> src/models/task_model.rs:26:10
   |
26 | #[derive(Insertable, Deserialize)]
   |          ^^^^^^^^^^ the trait `diesel::Expression` is not implemented for `chrono::datetime::DateTime<chrono::offset::utc::Utc>`
   |
   = note: required because of the requirements on the impl of `diesel::expression::AsExpression<diesel::sql_types::Timestamp>` for `chrono::datetime::DateTime<chrono::offset::utc::Utc>`
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `chrono::datetime::DateTime<chrono::offset::utc::Utc>: diesel::Expression` is not satisfied
  --> src/models/task_model.rs:26:10
   |
26 | #[derive(Insertable, Deserialize)]
   |          ^^^^^^^^^^ the trait `diesel::Expression` is not implemented for `chrono::datetime::DateTime<chrono::offset::utc::Utc>`
   |
   = note: required because of the requirements on the impl of `diesel::Expression` for `&chrono::datetime::DateTime<chrono::offset::utc::Utc>`
   = note: required because of the requirements on the impl of `diesel::expression::AsExpression<diesel::sql_types::Timestamp>` for `&chrono::datetime::DateTime<chrono::offset::utc::Utc>`
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `chrono::datetime::DateTime<chrono::offset::utc::Utc>: diesel::Expression` is not satisfied
  --> src/models/task_model.rs:26:10
   |
26 | #[derive(Insertable, Deserialize)]
   |          ^^^^^^^^^^ the trait `diesel::Expression` is not implemented for `chrono::datetime::DateTime<chrono::offset::utc::Utc>`
   |
   = note: required because of the requirements on the impl of `diesel::Expression` for `&'insert chrono::datetime::DateTime<chrono::offset::utc::Utc>`
   = note: required because of the requirements on the impl of `diesel::expression::AsExpression<diesel::sql_types::Timestamp>` for `&'insert chrono::datetime::DateTime<chrono::offset::utc::Utc>`
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 3 previous errors; 7 warnings emitted


task_model.rs

use diesel;
use diesel::prelude::*;
use serde_derive::{Serialize,Deserialize};
use rocket_contrib::json::Json;
use crate::schema::tasks;
use crate::schema::tasks::dsl::tasks as all_tasks;
use crate::DbConn;
use chrono::{DateTime, TimeZone, Utc, NaiveDateTime};
use chrono::serde::ts_seconds;


#[derive(Queryable, Serialize)]
pub struct Task {
    pub id: i32,
    pub name: String,
    pub arguments: String,
    pub priority: i32,
    pub done: bool,
    pub created_at: DateTime<Utc>,
    #[serde(default, deserialize_with = "option_datefmt")]
    pub start_time : Option<DateTime<Utc>>,
    #[serde(default, deserialize_with = "option_datefmt")]
    pub end_time : Option<DateTime<Utc>>,
}

#[derive(Insertable, Deserialize)]
#[table_name = "tasks"]
pub struct NewTask {
    pub name: String,
    pub arguments: String,
    pub priority: i32,
    pub created_at: DateTime<Utc>,
}

impl Task {
    pub fn insert(conn: DbConn, new_task: Json<NewTask>, ) -> bool {
        diesel::insert_into(tasks::table)
            .values(&new_task)
            .get_result(&*conn)
            .unwrap()

    }

    pub fn create(name: String,arguments: String,priority: i32, conn: DbConn) -> bool {
        let now = Utc::now().naive_utc();

        let new_task = NewTask {
            name: name,
            arguments: arguments,
            priority: priority,
            created_at: now
        };
        diesel::insert_into(tasks::table)
            .values(&new_task)
            .get_result(&*conn)
            .unwrap()

    }
}

option_datefmt.rs :

use chrono::{DateTime, TimeZone, Utc};
use serde::{Serialize,Deserialize,Deserializer};
use serde_derive::{Serialize,Deserialize};

const FORMAT: &str = "%Y-%m-%d %H:%M:%S";

fn datefmt<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
    where
        D: Deserializer<'de>,
{
    let s = String::deserialize(deserializer)?;
    Utc.datetime_from_str(&s, FORMAT)
        .map_err(serde::de::Error::custom)
}

fn option_datefmt<'de, D>(deserializer: D) -> Result<Option<DateTime<Utc>>, D::Error>
    where
        D: Deserializer<'de>,
{
    #[derive(Deserialize)]
    struct Wrapper(#[serde(deserialize_with = "datefmt")] DateTime<Utc>);

    let v = Option::deserialize(deserializer)?;
    Ok(v.map(|Wrapper(a)| a))
}

Cargo.toml :

[package]
name = "testrocket"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
diesel = { version = "1.4.0", features = ["postgres","chrono"] }
dotenv = "0.10"
chrono = { version = "0.4.11", features = ["serde"] }
serde = "1.0"
rocket = "0.4"

[dependencies.serde_derive]
version = "1.0"

[dependencies.rocket_contrib]
version = "0.4"
default-features = false
features = ["json","diesel_postgres_pool"]

Do you have an idea about how to fix it , please ? I'm stuck

I solved the issue by using the good serde and diesel version !
But now my errors are :


error[E0277]: the trait bound `&rocket_contrib::json::Json<models::task_model::NewTask>: diesel::Insertable<schema::tasks::table>` is not satisfied
  --> src/models/task_model.rs:39:21
   |
39 |             .values(&new_task)
   |                     ^^^^^^^^^ the trait `diesel::Insertable<schema::tasks::table>` is not implemented for `&rocket_contrib::json::Json<models::task_model::NewTask>`

error[E0277]: the trait bound `bool: diesel::deserialize::FromSql<(diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Integer, diesel::sql_types::Bool, diesel::sql_types::Timestamptz, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>), diesel::pg::Pg>` is not satisfied
  --> src/models/task_model.rs:40:14
   |
40 |             .get_result(&*conn)
   |              ^^^^^^^^^^ the trait `diesel::deserialize::FromSql<(diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Integer, diesel::sql_types::Bool, diesel::sql_types::Timestamptz, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>), diesel::pg::Pg>` is not implemented for `bool`
   |
   = help: the following implementations were found:
             <bool as diesel::deserialize::FromSql<diesel::sql_types::Bool, diesel::pg::Pg>>
   = note: required because of the requirements on the impl of `diesel::Queryable<(diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Integer, diesel::sql_types::Bool, diesel::sql_types::Timestamptz, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>), diesel::pg::Pg>` for `bool`
   = note: required because of the requirements on the impl of `diesel::query_dsl::LoadQuery<diesel::PgConnection, bool>` for `diesel::query_builder::InsertStatement<schema::tasks::table, _>`

error[E0277]: the trait bound `bool: diesel::deserialize::FromSql<(diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Integer, diesel::sql_types::Bool, diesel::sql_types::Timestamptz, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>), diesel::pg::Pg>` is not satisfied
  --> src/models/task_model.rs:56:14
   |
56 |             .get_result(&*conn)
   |              ^^^^^^^^^^ the trait `diesel::deserialize::FromSql<(diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Integer, diesel::sql_types::Bool, diesel::sql_types::Timestamptz, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>), diesel::pg::Pg>` is not implemented for `bool`
   |
   = help: the following implementations were found:
             <bool as diesel::deserialize::FromSql<diesel::sql_types::Bool, diesel::pg::Pg>>
   = note: required because of the requirements on the impl of `diesel::Queryable<(diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Integer, diesel::sql_types::Bool, diesel::sql_types::Timestamptz, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>), diesel::pg::Pg>` for `bool`
   = note: required because of the requirements on the impl of `diesel::query_dsl::LoadQuery<diesel::PgConnection, bool>` for `diesel::query_builder::InsertStatement<schema::tasks::table, diesel::query_builder::ValuesClause<(diesel::insertable::ColumnInsertValue<schema::tasks::columns::name, diesel::expression::bound::Bound<diesel::sql_types::Text, &std::string::String>>, diesel::insertable::ColumnInsertValue<schema::tasks::columns::arguments, diesel::expression::bound::Bound<diesel::sql_types::Text, &std::string::String>>, diesel::insertable::ColumnInsertValue<schema::tasks::columns::priority, diesel::expression::bound::Bound<diesel::sql_types::Integer, &i32>>, diesel::insertable::ColumnInsertValue<schema::tasks::columns::created_at, diesel::expression::bound::Bound<diesel::sql_types::Timestamptz, &chrono::datetime::DateTime<chrono::offset::utc::Utc>>>), schema::tasks::table>>`


What did I do wrong in this first example ? :confused:

error[E0277]: the trait bound `&rocket_contrib::json::Json<models::task_model::NewTask>: diesel::Insertable<schema::tasks::table>` is not satisfied
  --> src/models/task_model.rs:39:21
   |
39 |             .values(&new_task)
   |                     ^^^^^^^^^ the trait `diesel::Insertable<schema::tasks::table>` is not implemented for `&rocket_contrib::json::Json<models::task_model::NewTask>`

For this error try .values(&*new_task). This should go from &Json<NewTask> to &NewTask. For the second and third errors I don't know what the problem is.

The second and third error is coming from the fact that get_result() returns no boolean, but a generic type that represents the result of your query. Let's have a look at the documentation for the exact definition of get_result:

fn get_result<U>(self, conn: &Conn) -> QueryResult<U> where
    Self: LoadQuery<Conn, U>, 

It returns a Result variant with the Ok variant set to U where the generic type U needs to fullfil the trait bound Self: LoadQuery<Conn, U>. The generic type Conn seems to be just the type of the concrete connection implementation here. Self is the type of our query, more on that later on. For more details we need to look at the documentation of LoadQuery](LoadQuery in diesel::query_dsl::methods - Rust). The interesting part here is the implementors section down that page, especially this one:

impl<Conn, T, U> LoadQuery<Conn, U> for T where
    Conn: Connection,
    Conn::Backend: HasSqlType<T::SqlType>,
    T: AsQuery + RunQueryDsl<Conn>,
    T::Query: QueryFragment<Conn::Backend> + QueryId,
    U: Queryable<T::SqlType, Conn::Backend>, 

Now that are lot's of trait bounds, but let's break down that a bit:
We already now that Conn is our connection type. T corresponds to Self in our last definition, so that's the type of our query. U is our return type, so that type where we try to get some idea which type should actually be used here.
Now there is only one trait bound that involves U: U: Queryable<T::SqlType, Conn::Backend>. That means U must definitively be some type that implements Queryable, which makes sense as diesels documentation describes Queryable as trait which markes types that are results of queries. Now there are two generic parameters here:

  • T::SqlType: Remember T is our query. T::SqlType is now some associated type from some trait implemented by our query (It's coming from AsQuery to be exact, but that does not really matter here). If we now look at our error message we can see that this type is actually (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Integer, diesel::sql_types::Bool, diesel::sql_types::Timestamptz, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>) (that's coming from the first note: line emitted by rustc). Now this looks much like a representation of fields returned by your query, and in fact that's true. So this type corresponds to which fields are returned by your query and verifies that the actual type on rust side matches these fields.
  • Conn::Backend: Which means the Queryable implementation can be dependent on the actual used database type. That makes sense as not all database systems support the same datatypes.

So now the question is which type should we actually use for U here?. Let's count the number of fields in T::SqlType first. That are 8 fields. Now you have exactly one type in your code snippets that somehow mentions Queryable (by deriving it), and that's the Task type with also 8 fields. Additionally it looks like each field in T::SqlType corresponds to a field in your Task type. id is an i32 which is compatible with diesel::sql_types::Integer and so on. Task is a valid type for U which means get_result() will return a QueryResult<Task> in this case (Technically speaking any other type implementing Queryable with the same bounds would also be valid).

So now the short version for all that one that don't want to read all this trait bound stuff:
You need to change the return type of Task::create and Task::insert to Task instead of using bool there.

thank you !

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.