diesel::prelude

Macro joinable

Source
macro_rules! joinable {
    ($($child:ident)::* -> $($parent:ident)::* ($source:ident)) => { ... };
}
Expand description

Allow two tables to be referenced in a join query without providing an explicit ON clause.

The generated ON clause will always join to the primary key of the parent table. This macro removes the need to call [.on] explicitly, you will still need to invoke allow_tables_to_appear_in_same_query! for these two tables to be able to use the resulting query, unless you are using diesel print-schema which will generate it for you.

If you are using diesel print-schema, an invocation of this macro will be generated for every foreign key in your database unless one of the following is true:

  • The foreign key references something other than the primary key
  • The foreign key is composite
  • There is more than one foreign key connecting two tables
  • The foreign key is self-referential

ยงExample

use schema::*;

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

let implicit_on_clause = users::table.inner_join(posts::table);
let implicit_on_clause_sql = diesel::debug_query::<DB, _>(&implicit_on_clause).to_string();

let explicit_on_clause = users::table
    .inner_join(posts::table.on(posts::user_id.eq(users::id)));
let explicit_on_clause_sql = diesel::debug_query::<DB, _>(&explicit_on_clause).to_string();

assert_eq!(implicit_on_clause_sql, explicit_on_clause_sql);

In the example above, the line joinable!(posts -> users (user_id));

specifies the relation of the tables and the ON clause in the following way:

child_table -> parent_table (foreign_key)

  • parent_table is the Table with the Primary key.

  • child_table is the Table with the Foreign key.

So given the Table declaration from Associations docs

  • The parent table would be User
  • The child table would be Post
  • and the Foreign key would be Post.user_id

For joins that do not explicitly use on clauses via JoinOnDsl the following on clause is generated implicitly:

post JOIN users ON posts.user_id = users.id