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

Diesel does not produce `belonging_to()` for structs annotated with `belongs_to` #1203

Closed
berkus opened this Issue Sep 25, 2017 · 5 comments

Comments

Projects
None yet
2 participants
@berkus

berkus commented Sep 25, 2017

Setup

Versions

  • Rust: rustc 1.22.0-nightly (1ed7d41d8 2017-09-24)
  • Diesel: 0.16.0
  • Database: postgresql 9.6.2
  • Operating System macos sierra 10.12.6

Feature Flags

  • diesel: postgres, chrono
  • diesel_codegen: postgres

Problem Description

#[derive(Queryable, Serialize, Identifiable)]
#[has_many(categories)]
pub struct User {
    pub id: i32,
    pub username: String,
}

#[derive(Queryable, Serialize, Identifiable, Associations)]
#[table_name = "categories"]
#[belongs_to(User, foreign_key = "username")]
pub struct Category {
    pub id: i32,
    pub username: String,
}

[... later in main.rs ...]

        let user: User = users.find(1).first(connection).expect("Error loading user");
        let cats = Category::belonging_to(&user).load(connection).expect("Error loading cats");

gives

error[E0599]: no function or associated item named `belonging_to` found for type `models::Category` in the current scope
   --> src/main.rs:157:20
    |
157 |         let cats = Category::belonging_to(&user).load(connection).expect(
    |                     ^^^^^^^^^^^^^^^^^^^^^^

What are you trying to accomplish?

Link two tables using the belonging_to()

What is the expected output?

Should compile at least.

What is the actual output?

Regardless of whether these tables have a foreign key relation on DB or not, there's no belonging_to() function to call.

Are you seeing any additional errors?

No. Warnings:

warning: unused attribute
 --> src/models.rs:8:1
  |
8 | #[has_many(categories)]
  | ^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: #[warn(unused_attributes)] on by default

Steps to reproduce

models.rs as above.

schema.rs (from diesel print-schema):

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

table! {
    categories (id) {
        id -> Int4,
        username -> Varchar,
    }
}

Checklist

  • I have already looked over the issue tracker for similar issues.
@sgrif

This comment has been minimized.

Member

sgrif commented Sep 25, 2017

Please provide your full compiler output

@berkus

This comment has been minimized.

berkus commented Sep 26, 2017

I will send you full project repo in a bit.

@berkus

This comment has been minimized.

berkus commented Sep 26, 2017

Here's the repo: https://github.com/berkus/diesel-belongs-to-bug/blob/master/README.md

steps to reproduce:

  1. git clone https://github.com/berkus/diesel-belongs-to-bug
  2. cd diesel-belongs-to-bug
  3. cargo run

(i'm using nightly jfyi)

@sgrif

This comment has been minimized.

Member

sgrif commented Sep 26, 2017

I reduced your repro case to this minimal case:

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

use diesel::prelude::*;

table! {
    users {
        id -> Int4,
        username -> Varchar,
    }
}

table! {
    categories {
        id -> Int4,
        username -> Varchar,
    }
}

#[derive(Identifiable)]
pub struct User {
    pub id: i32,
    pub username: String,
}

#[derive(Identifiable, Associations)]
#[table_name = "categories"]
#[belongs_to(User, foreign_key = "username")]
pub struct Category {
    pub id: i32,
    pub username: String,
}

fn main() {
    let user = User { id: 1, username: "".into() };
    let cats = Category::belonging_to(&user);
}

by switching to UFCS (<Category as BelongingToDsl<&User>>::belonging_to(&user)) we get a much clearer error message:

error[E0277]: the trait bound `diesel::query_builder::SelectStatement<categories::table>: diesel::FilterDsl<diesel::expression::operators::Eq<categories::columns::username, &i32>>` is not satisfied
  --> src/main.rs:36:16
   |
36 |     let cats = <Category as BelongingToDsl<&User>>::belonging_to(&user);
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `diesel::FilterDsl<diesel::expression::operators::Eq<categories::columns::username, &i32>>` is not implemented for `diesel::query_builder::SelectStatement<categories::table>`
   |
   = help: the following implementations were found:
             <diesel::query_builder::SelectStatement<F, S, D, W, O, L, Of, G> as diesel::FilterDsl<Predicate>>
   = note: required because of the requirements on the impl of `diesel::FilterDsl<diesel::expression::operators::Eq<categories::columns::username, &i32>>` for `categories::table`

error[E0277]: the trait bound `i32: diesel::Expression` is not satisfied
  --> src/main.rs:36:16
   |
36 |     let cats = <Category as BelongingToDsl<&User>>::belonging_to(&user);
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `diesel::Expression` is not implemented for `i32`
   |
   = note: required because of the requirements on the impl of `diesel::Expression` for `&i32`
   = note: required because of the requirements on the impl of `diesel::expression::AsExpression<diesel::types::Text>` for `&i32`
   = note: required because of the requirements on the impl of `diesel::BelongingToDsl<&User>` for `Category`

You are attempting to use the field username as the foreign key, but the primary key of user is id which has the type Integer. You cannot compare an integer and text column.

@sgrif sgrif closed this Sep 26, 2017

@berkus

This comment has been minimized.

berkus commented Sep 26, 2017

Thanks!

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