Diesel: [E0277]: the trait bound `i32: diesel::types::FromSqlRow<diesel::types::Nullable<diesel::types::Integer>, diesel::pg::Pg>` is not satisfied

Created on 15 May 2016  ·  14Comments  ·  Source: diesel-rs/diesel

2016-05-15 11-48-45
Hello, when I try to use diesel to build my first orm, and error is come. My way is exactly same to your getting-start doc.
up.sql:

CREATE TABLE USERS (
    uid VARCHAR PRIMARY KEY,
    realname VARCHAR NOT NULL,
    age INTEGER,
    sex VARCHAR
);

down.sql:

DROP TABLE USERS;

.env:

DATABASE_URL=postgres://postgres:postgres@localhost/simllsan

and the command diesel migration redo has been executed successfully :

fuying@fuying-linux:~/rustprojs/simtraining$ diesel migration redo
Rolling back migration 20160514210851
Running migration 20160514210851

lib.rs:

#![feature(custom_derive, custom_attribute, plugin)]
#![plugin(serde_macros, diesel_codegen, dotenv_macros)]

#[macro_use]
extern crate diesel;
extern crate dotenv;

extern crate serde;
extern crate serde_json;

extern crate time;
extern crate rand;
extern crate libc;
extern crate mio;
#[cfg(windows)]
extern crate winapi;
#[cfg(windows)]
extern crate ws2_32;

pub mod jizu;
pub mod simctrl;
pub mod util;
pub mod zhiling;
pub mod dianzhan;
pub mod duanluqi;
pub mod fuzai;
pub mod node;
pub mod zhilu;
pub mod xitong;

pub mod schema;
pub mod user;
// pub mod evaluation;
// pub mod projects;
// pub mod station;
// pub mod training;
use diesel::prelude::*;
use diesel::pg::PgConnection;
use dotenv::dotenv;
use std::env;
use diesel::result::Error;
use user::{User, NewUser};

pub fn establish_connection() -> PgConnection {
    dotenv().ok();

    let database_url = env::var("DATABASE_URL")
        .expect("DATABASE_URL must be set");
    PgConnection::establish(&database_url)
        .expect(&format!("Error connecting to {}", database_url))
}

pub fn create_user<'a>(conn: &PgConnection,
                  _uid: &'a str,
                  _realname: &'a str,
                  _age: i32,
                  _sex: &'a str)
                  -> QueryResult<User> {
    use schema::users;
    let uid_s = String::from(_uid);

    let result = users::table.find(uid_s).first(conn);
    match result {
        Err(NotFound) => {
            let new_user = NewUser {
                uid: _uid,
                realname: _realname,
                age : _age,
                sex : _sex,
            };
            return diesel::insert(&new_user).into(users::table)
                .get_result(conn);
        }
        Ok(_) => return Err(Error::DatabaseError("此用户名已存在".to_string())),
    }
}

schema.rs:

infer_schema!(dotenv!("DATABASE_URL"));

user.rs:

use super::schema::users;
#[derive(PartialEq, Copy, Clone, Debug, Serialize, Deserialize)]
pub enum Sex {
    Male,
    Female,
    Unisex,
}
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize, Queryable)]
pub struct User {
    pub uid: String,
    pub realname: String,
    pub age: i32,
    pub sex: String,
}

#[insertable_into(users)]
pub struct NewUser<'a> {
    pub uid: &'a str,
    pub realname: &'a str,
    pub age: i32,
    pub sex: &'a str,
}

impl User {
    pub fn new(_id: &str, _realname: &str) -> User {
        User {
            uid: String::from(_id),
            realname: String::from(_realname),
            age: 0,
            sex: "".to_string(),
        }
    }

}

Most helpful comment

This is correct. You cannot deserialize a column of type Nullable<Integer> into an i32. You'll either need to use an Option<i32> on the Rust side, or change the field to be NOT NULL on the SQL side.

All 14 comments

I use ubuntu 15.10, and the version of rust is:

fuying@fuying-linux:~/rustprojs/simtraining$ rustc --version
rustc 1.10.0-nightly (d91f8ab0f 2016-05-07)
fuying@fuying-linux:~/rustprojs/simtraining$ cargo --version
cargo 0.11.0-nightly (b304305 2016-05-06)

cargo.toml:

[package]
name = "simtraining"
version = "0.1.0"
authors = ["fuying"]

[dependencies]
time = "^0.1"
rand = "^0.3"
libc = "^0.2"
mio = "^0.5"
serde = "^0.7.0"
serde_json = "^0.7.0"
serde_macros = "^0.7.0"
iron = "^0.3.0"
router = "^0.1.1"
diesel = { git = "https://github.com/diesel-rs/diesel.git" }
diesel_codegen = { git = "https://github.com/diesel-rs/diesel.git", default-features = false, features = ["nightly", "postgres"] }
dotenv = "^0.8.0"
dotenv_macros = "^0.8.0"

[dev-dependencies]
rand = "^0.3"

[target.x86_64-pc-windows-msvc.dependencies]
winapi = "^0.2"
ws2_32-sys = "^0.2"
[target.x86_64-pc-windows-gnu.dependencies]
winapi = "^0.2"
ws2_32-sys = "^0.2"
[target.i686-pc-windows-msvc.dependencies]
winapi = "^0.2"
ws2_32-sys = "^0.2"

[[example]]
name = "test-router"
path = "examples/testrouter.rs"

[[example]]
name = "test-create-user"
path = "examples/testcreateuser.rs"

This is correct. You cannot deserialize a column of type Nullable<Integer> into an i32. You'll either need to use an Option<i32> on the Rust side, or change the field to be NOT NULL on the SQL side.

@sgrif
thank you very much

@sgrif
sorry to bother you. Another question is how can i deserialize an embedded struct obiect? It likes this:

[derive(Queryable)]

[insert_into(users)]

struct User {
//...
}

[derive(Queryable)]

[insert_into(posts)]

struct Post {
//...
user : User
}

Does it correct? Because I am outside and can't test it. So if you are not busy, please help me.
By the way, does diesel support json or jsonb type? And if diesel can support it, where can I find its docs and how to use it? Thank you very much.

We don't really have support for embedded structs at the moment. When you're querying against two tables, you'd get back a (Post, User) instead of embedding the parent record inside of the child. If you _really_ want to embed a struct, you'll need to implement FromSqlRow for your User struct manually. It'd look something like this:

use diesel::prelude::*;
use diesel::backend::Backend;
use diesel::types::{FromSqlRow + HasSqlType};
use diesel::row::Row;
use std::error::Error;

impl<ST, DB> FromSqlRow<ST, DB> for User where
    DB: Backend + HasSqlType<ST>,
    User: Queryable<ST, DB>,
    <User as Queryable<ST, DB>>::Row: FromSqlRow<ST, DB>,
{
    fn build_from_row<T: Row<DB>>(row: &mut T) -> Result<Self, Box<Error + Send + Sync>> {
        let row = try!(<<User as Queryable<ST, DB>>::Row as FromSqlRow<ST, DB>>::build_from_row(row));
        Ok(User::build(row))
    }
}

Note: Haven't tried that exact code, that's just from memory of what it'd roughly look like.

We don't support the JSON type yet, but it's on the radar for something we'd like to support. https://github.com/diesel-rs/diesel/issues/44 is the tracking issue, and I've mentioned how you could use it today in your app if needed in the comments there.

@sgrif
thank you very much.

@sgrif
thank you very much.

Just a note, I faced similar issue. it's important that after you've made changes to the migration, run

cargo clean

From my limited understanding, I assume the custom code generator does not update the generated code and uses the old database definition, So we need to clean the generated code

I am sorry, for least clear explanation as I'm sleepy and just figured out the problem. I hope it helps someone.

@tmahmood thank you :) your solution solved my issue

If you ever land here looking for solution to not implemented traits compilation errors make sure that your model declaration fields follow exact order of fields in your table.

This is correct. You cannot deserialize a column of type Nullable<Integer> into an i32. You'll either need to use an Option<i32> on the Rust side, or change the field to be NOT NULL on the SQL side.

This solution solves my issue! Thanks!!

@mplebanski Thank you for your comment! I have tried to understand and solve a similar issue for an hour now, and randomly I saw your comment which fixed it all 🎉

I simply changed the field order in my struct to match my up.sql migration and everthing compiles.

That the field order matters should be written in capital letters somewhere.

@skovmand That is already mentioned in multiple locations like the getting started guide or the documentation of the Queryable derive
If you have another location in mind where you expect this information please open a PR.

Thank you for the reference, which explains it clearly 👍 . Perhaps I was overwhelmed by new information :-)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kollapsderwellenfunktion picture kollapsderwellenfunktion  ·  4Comments

killercup picture killercup  ·  3Comments

qmx picture qmx  ·  3Comments

killercup picture killercup  ·  4Comments

gliderkite picture gliderkite  ·  3Comments