New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some(diesel::expression::now) fails to set Nullable<Timestamp> value #911

Closed
Nemo157 opened this Issue May 15, 2017 · 2 comments

Comments

Projects
None yet
2 participants
@Nemo157

Nemo157 commented May 15, 2017

Judging by impl Expression<SqlType = Timestamp> for now + impl<T, ST> AsExpression<Nullable<ST>> for Option<T> where ST: NotNull it seems like this should work, and the error message makes me think it has made it past that stage of the type checking, but for some reason the resulting UpdateStatement doesn't implement ExecuteDsl.

A workaround is to just use diesel::expression::sql to bypass the type checking and inject CURRENT_TIMESTAMP directly: baz.eq(sql("CURRENT_TIMESTAMP")).

diesel = { version = "0.12.0", features = ["postgres"] }
cargo-0.17.0-nightly (f9e5481 2017-03-03)
rustc 1.16.0 (30cf806ef 2017-03-10)
#[macro_use]
extern crate diesel;

table! {
    foo {
        id -> Int4,
        bar -> Timestamp,
        baz -> Nullable<Timestamp>,
    }
}

pub fn foo(pg: &diesel::pg::PgConnection) {
    use diesel::prelude::*;
    use diesel::update;
    use foo::dsl::{foo, id, bar, baz};

    // This fails to compile because of the `baz.eq(Some(now))` line,
    // comment that out and it will work
    {
        use diesel::expression::now;
        update(foo.filter(id.eq(4)))
            .set((
                bar.eq(now),
                baz.eq(Some(now))
            ))
            .execute(pg)
            .unwrap();
    }
}
error: no method named `execute` found for type `diesel::query_builder::UpdateStatement<foo::table, diesel::query_builder::where_clause::WhereClause<diesel::expression::predicates::Eq<foo::columns::id, diesel::expression::bound::Bound<diesel::types::Integer, i32>>>, (diesel::expression::predicates::Eq<foo::columns::bar, diesel::expression::now>, diesel::expression::predicates::Eq<foo::columns::baz, diesel::expression::bound::Bound<diesel::types::Nullable<diesel::types::Timestamp>, std::option::Option<diesel::expression::now>>>)>` in the current scope
  --> src/lib.rs:26:14
   |
26 |             .execute(pg)
   |              ^^^^^^^
   |
   = note: the method `execute` exists but the following trait bounds were not satisfied: `diesel::query_builder::UpdateStatement<foo::table, diesel::query_builder::where_clause::WhereClause<diesel::expression::predicates::Eq<foo::columns::id, diesel::expression::bound::Bound<diesel::types::Integer, i32>>>, (diesel::expression::predicates::Eq<foo::columns::bar, diesel::expression::now>, diesel::expression::predicates::Eq<foo::columns::baz, diesel::expression::bound::Bound<diesel::types::Nullable<diesel::types::Timestamp>, std::option::Option<diesel::expression::now>>>)> : diesel::query_builder::QueryFragment<_>`, `&diesel::query_builder::UpdateStatement<foo::table, diesel::query_builder::where_clause::WhereClause<diesel::expression::predicates::Eq<foo::columns::id, diesel::expression::bound::Bound<diesel::types::Integer, i32>>>, (diesel::expression::predicates::Eq<foo::columns::bar, diesel::expression::now>, diesel::expression::predicates::Eq<foo::columns::baz, diesel::expression::bound::Bound<diesel::types::Nullable<diesel::types::Timestamp>, std::option::Option<diesel::expression::now>>>)> : diesel::query_builder::QueryFragment<_>`, `&mut diesel::query_builder::UpdateStatement<foo::table, diesel::query_builder::where_clause::WhereClause<diesel::expression::predicates::Eq<foo::columns::id, diesel::expression::bound::Bound<diesel::types::Integer, i32>>>, (diesel::expression::predicates::Eq<foo::columns::bar, diesel::expression::now>, diesel::expression::predicates::Eq<foo::columns::baz, diesel::expression::bound::Bound<diesel::types::Nullable<diesel::types::Timestamp>, std::option::Option<diesel::expression::now>>>)> : diesel::query_builder::QueryFragment<_>`, `&mut diesel::query_builder::UpdateStatement<foo::table, diesel::query_builder::where_clause::WhereClause<diesel::expression::predicates::Eq<foo::columns::id, diesel::expression::bound::Bound<diesel::types::Integer, i32>>>, (diesel::expression::predicates::Eq<foo::columns::bar, diesel::expression::now>, diesel::expression::predicates::Eq<foo::columns::baz, diesel::expression::bound::Bound<diesel::types::Nullable<diesel::types::Timestamp>, std::option::Option<diesel::expression::now>>>)> : diesel::query_builder::QueryId`
@sgrif

This comment has been minimized.

Member

sgrif commented May 15, 2017

Some is for use with Rust types. now corresponds to the SQL CURRENT_TIMESTAMP expression. Combining the two doesn't make sense. You probably want now.nullable()

@sgrif sgrif closed this May 15, 2017

@Nemo157

This comment has been minimized.

Nemo157 commented May 15, 2017

Ok, I think I understand, there's actually sort of two parallel worlds of Rust values and SQL expressions which use either Option or Nullable for wrapping non-nullable entities into nullable ones. It would be great if the API docs could mention this somehow, but I guess putting something on the impl<T, ST> AsExpression<Nullable<ST>> for Option<T> where ST: NotNull needs rust-lang/rust#18701 still.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment