Skip to content
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

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

Closed
liuwa666 opened this issue May 15, 2016 · 15 comments

Comments

@liuwa666
Copy link

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(),
        }
    }

}
@liuwa666
Copy link
Author

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"

@sgrif
Copy link
Member

sgrif commented May 15, 2016

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 sgrif closed this as completed May 15, 2016
@liuwa666
Copy link
Author

@sgrif
thank you very much

@liuwa666
Copy link
Author

@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.

@sgrif
Copy link
Member

sgrif commented May 15, 2016

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. #44 is the tracking issue, and I've mentioned how you could use it today in your app if needed in the comments there.

@liuwa666
Copy link
Author

@sgrif
thank you very much.

1 similar comment
@liuwa666
Copy link
Author

@sgrif
thank you very much.

@tmahmood
Copy link

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.

@theredfish
Copy link
Contributor

theredfish commented Sep 3, 2017

@tmahmood thank you :) your solution solved my issue

@mplebanski
Copy link

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.

@jiuneypachevitch
Copy link

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!!

@skovmand
Copy link

@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.

@weiznich
Copy link
Member

@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.

@skovmand
Copy link

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

@crlsktr
Copy link

crlsktr commented Jul 8, 2022

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.

I owe you lunch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants