Daniel
Daniel

Reputation: 434

Diesel join cannot infer type

rust version 1.18.3 diesel version 1.0.0 postgres 11 on debian 10

I am trying to join two tables in Rust utilizing the Diesel ORM and postgres. The table are posts and users and I'd like to join the user name from users to the posts table.

I have implemented a foreign key in posts in the CREATE TABLE statement pointing to the id in users so diesel automatically derived the joinable! and the allow_tables_to_appear_in_same_query! macro in schema.rs. Yet when I try to join the tables in my code rust cannot infer the type and I can't figure how to annotate the type.

this is my main.rs

extern crate cmsbackend;
extern crate diesel;

use self::cmsbackend::*;
use self::models::*;
use self::diesel::prelude::*;

fn main() {
    use cmsbackend::schema::*;

    let connection = establish_connection();

    let results = users::table.inner_join(posts::table)
        .select((users::name, posts::title))
        .load(&connection);
}

I get this error message:

error[E0282]: type annotations needed for `std::result::Result<std::vec::Vec<U>, diesel::result::Error>`
  --> src/bin/main.rs:20:10
   |
18 |     let results = users::table.inner_join(posts::table)
   |         ------- consider giving `results` the explicit type `std::result::Result<std::vec::Vec<U>, diesel::result::Error>`, where the type parameter `U` is specified
19 |         .select((users::name, posts::title))
20 |         .load(&connection);
   |          ^^^^ cannot infer type for `U`

For more information about this error, try rustc --explain E0282. error: Could not compile cmsbackend.

Is it possible that I need to derive something else in my struct definitions:

use diesel::pg::data_types::*;

#[derive(Queryable)]
pub struct Post {
    pub id: i32,
    pub title: String,
    pub body: Option<String>,
    pub published: bool,
    pub user_id: i32,
    pub creation_date: PgTimestamp,
    pub last_edit: PgTimestamp,
    pub foto: Option<String>,
}

#[derive(Queryable)]
pub struct User {
    pub id: i32,
    pub name: String,
    pub pw: String,
}

How do I get this to compile?


Edit:
Thanks for your comments. This is the content of my schema.rs

table! {
    posts (id) {
        id -> Int4,
        title -> Varchar,
        body -> Nullable<Text>,
        published -> Bool,
        user_id -> Int4,
        creation_date -> Timestamp,
        last_edit -> Timestamp,
        foto -> Nullable<Varchar>,
    }
}

table! {
    users (id) {
        id -> Int4,
        name -> Varchar,
        pw -> Varchar,
    }
}

joinable!(posts -> users (user_id));

allow_tables_to_appear_in_same_query!(
    posts,
    users,
);

Upvotes: 2

Views: 3966

Answers (1)

Daniel
Daniel

Reputation: 434

I have solved this. Since the Queryable derive in the structs can not infer the type of the data resulting from the join you have to annotate the data types of the struct fields like so:

let data: Vec<(String, String)> = users::table.inner_join(notes::table)
    .select((users::name, notes::title))
    .load(&connection)
    .expect("error");

Before I tryed something like

let data: Vec<(User, Post)> = posts::table.inner_join(users::table)
.select((users::name, notes::title))
.load(&connection)
.expect("error");

The compiler threw an error for load that the trait Queryable is not implemented.

Also see the documentation: https://github.com/diesel-rs/diesel/blob/master/guide_drafts/trait_derives.md

Upvotes: 4

Related Questions