#[derive(HasQuery)]
{
// Attributes available to this derive:
#[diesel]
}
Expand description
Implements HasQuery
This derive implements a common entry point for building queries based on a model like Rust struct. It enables you to always have a certain base query associated with a given type. This derive is designed to easily couple your query with your Rust type. It’s important to note that for Diesel this mapping happens always on query and not on table level, which enables you to write several queries related to the same table, while a single query could be related to zero or multiple tables.
By default this derive will use the equivalent of SELECT your, fields FROM your_types
which implies that it needs to know the corresponding table type. As with any other
diesel derive it uses the snake_case
type name with an added s
if no other
name is specified.
It is possible to change this default by using #[diesel(table_name = something)]
.
If you would like to use a more complex query as base query you can overwrite the standard
query by using the #[diesel(base_query = your_type::table.filter(your_type::is_admin.eq(true)))]
attribute to overwrite the automatically generated base query. This derive will still apply
a select clause that matches your type. By default it also tries to infer the correct
type of that query. This type can be overwritten by using the #[diesel(base_query_type)]
attribute.
This derive will internally implement the following traits:
HasQuery
Selectable
(for building the selection)Queryable
(for allowing to load results from the database)
For the later two traits see their corresponding derives for supported options:
Any option documented there is also supported by this derive
In contrast to #[derive(Selectable)]
this derive automatically enables
#[diesel(check_for_backend(_))]
with all backends enabled at compile time
if no explicit #[diesel(check_for_backend(_))]
attribute is given. This
will lead to better error messages. You
can use #[diesel(check_for_backend(disable = true))]
to disable this behaviour
for that particular instance.
§Attributes
§Optional Type attributes
#[diesel(base_query = _)]
specifies a base query associated with this type. It may be used in conjunction withbase_query_type
(described below)#[diesel(base_query_type = _)]
the Rust type described by thebase_query
attribute. Usually diesel is able to infer this type, but for complex types such an annotation might be required. This will be required if a custom function call that doesn’t have the corresponding associated type defined at the same path appears in your query.#[diesel(table_name = path::to::table)]
, specifies a path to the table for which the current type is selectable. The path is relative to the current module. If this attribute is not used, the type name converted tosnake_case
with an addeds
is used as table name.#[diesel(check_for_backend(diesel::pg::Pg, diesel::mysql::Mysql))]
, instructs the derive to generate additional code to identify potential type mismatches. It accepts a list of backend types to check the types against. If this option is not set this derive automatically uses all backends enabled at compile time for this check. You can disable this behaviour via#[diesel(check_for_backend(disable = true))]
§Optional Field Attributes
#[diesel(column_name = some_column)]
, overrides the column name for a given field. If not set, the name of the field is used as column name.#[diesel(embed)]
, specifies that the current field maps not only a single database column, but is a type that implementsSelectable
on its own#[diesel(select_expression = some_custom_select_expression)]
, overrides the entire select expression for the given field. It may be used to select with custom tuples, or specifyselect_expression = my_table::some_field.is_not_null()
, or separate tables… It may be used in conjunction withselect_expression_type
(described below)#[diesel(select_expression_type = the_custom_select_expression_type]
, should be used in conjunction withselect_expression
(described above) if the type is too complex for diesel to infer it automatically. This will be required if select_expression is a custom function call that doesn’t have the corresponding associated type defined at the same path. Example use (this would actually be inferred):#[diesel(select_expression_type = dsl::IsNotNull<my_table::some_field>)]
#[diesel(deserialize_as = Type)]
, instead of deserializing directly into the field type, the implementation will deserialize intoType
. ThenType
is converted via.try_into
into the field type. By default, this derive will deserialize directly into the field type
§Examples
§Basic usage
// it's important to have the right table in scope
use schema::users;
#[derive(HasQuery, PartialEq, Debug)]
struct User {
id: i32,
name: String,
}
// equivalent to `users::table.select(User::as_select()).first(connection)?;
let first_user = User::query().first(connection)?;
let expected = User { id: 1, name: "Sean".into() };
assert_eq!(expected, first_user);
§Custom base query
// it's important to have the right table in scope
use schema::{users, posts};
#[derive(HasQuery, PartialEq, Debug)]
struct Post {
id: i32,
user_id: i32,
title: String,
}
#[derive(HasQuery, PartialEq, Debug)]
#[diesel(base_query = users::table.inner_join(posts::table).order_by(users::id))]
// that's required to let the derive understand
// from which table the columns should be selected
#[diesel(table_name = users)]
struct UserWithPost {
id: i32,
name: String,
#[diesel(embed)]
post: Post,
}
// equivalent to users::table.inner_join(posts::table)
// .order_by(users::id)
// .select(UserWithPost::as_select()).first(connection)?;
let first_user = UserWithPost::query().first(connection)?;
let expected = UserWithPost { id: 1, name: "Sean".into(), post: Post {id: 1, user_id: 1, title: "My first post".into() } };
assert_eq!(expected, first_user);
§Expanded Code
Expanded Code
§SQLite
§Input
#[derive(HasQuery)]
struct User {
id: i32,
name: String,
}
§Expanded Code
The macro expands the input to the following Rust code:
const _: () = {
use diesel;
impl<__DB: diesel::backend::Backend> diesel::HasQuery<__DB> for User {
type BaseQuery = <users::table as diesel::query_builder::AsQuery>::Query;
fn base_query() -> Self::BaseQuery {
diesel::query_builder::AsQuery::as_query(users::table)
}
}
};
const _: () = {
use diesel;
use diesel::expression::Selectable;
impl<__DB: diesel::backend::Backend> Selectable<__DB> for User {
type SelectExpression = (users::r#id, users::r#name);
fn construct_selection() -> Self::SelectExpression {
(users::r#id, users::r#name)
}
}
fn _check_field_compatibility()
where
i32: diesel::deserialize::FromSqlRow<
diesel::dsl::SqlTypeOf<users::r#id>,
diesel::sqlite::Sqlite,
>,
String: diesel::deserialize::FromSqlRow<
diesel::dsl::SqlTypeOf<users::r#name>,
diesel::sqlite::Sqlite,
>,
{}
};
const _: () = {
use diesel;
use diesel::row::{Row as _, Field as _};
impl<
__DB: diesel::backend::Backend,
__ST0,
__ST1,
> diesel::deserialize::Queryable<(__ST0, __ST1), __DB> for User
where
(i32, String): diesel::deserialize::FromStaticSqlRow<(__ST0, __ST1), __DB>,
{
type Row = (i32, String);
fn build(row: (i32, String)) -> diesel::deserialize::Result<Self> {
use std::convert::TryInto;
Ok(Self {
id: row.0.try_into()?,
name: row.1.try_into()?,
})
}
}
};
§PostgreSQL
§Input
#[derive(HasQuery)]
struct User {
id: i32,
name: String,
}
§Expanded Code
The macro expands the input to the following Rust code:
const _: () = {
use diesel;
impl<__DB: diesel::backend::Backend> diesel::HasQuery<__DB> for User {
type BaseQuery = <users::table as diesel::query_builder::AsQuery>::Query;
fn base_query() -> Self::BaseQuery {
diesel::query_builder::AsQuery::as_query(users::table)
}
}
};
const _: () = {
use diesel;
use diesel::expression::Selectable;
impl<__DB: diesel::backend::Backend> Selectable<__DB> for User {
type SelectExpression = (users::r#id, users::r#name);
fn construct_selection() -> Self::SelectExpression {
(users::r#id, users::r#name)
}
}
fn _check_field_compatibility()
where
i32: diesel::deserialize::FromSqlRow<
diesel::dsl::SqlTypeOf<users::r#id>,
diesel::pg::Pg,
>,
String: diesel::deserialize::FromSqlRow<
diesel::dsl::SqlTypeOf<users::r#name>,
diesel::pg::Pg,
>,
{}
};
const _: () = {
use diesel;
use diesel::row::{Row as _, Field as _};
impl<
__DB: diesel::backend::Backend,
__ST0,
__ST1,
> diesel::deserialize::Queryable<(__ST0, __ST1), __DB> for User
where
(i32, String): diesel::deserialize::FromStaticSqlRow<(__ST0, __ST1), __DB>,
{
type Row = (i32, String);
fn build(row: (i32, String)) -> diesel::deserialize::Result<Self> {
use std::convert::TryInto;
Ok(Self {
id: row.0.try_into()?,
name: row.1.try_into()?,
})
}
}
};
§MySQL
§Input
#[derive(HasQuery)]
struct User {
id: i32,
name: String,
}
§Expanded Code
The macro expands the input to the following Rust code:
const _: () = {
use diesel;
impl<__DB: diesel::backend::Backend> diesel::HasQuery<__DB> for User {
type BaseQuery = <users::table as diesel::query_builder::AsQuery>::Query;
fn base_query() -> Self::BaseQuery {
diesel::query_builder::AsQuery::as_query(users::table)
}
}
};
const _: () = {
use diesel;
use diesel::expression::Selectable;
impl<__DB: diesel::backend::Backend> Selectable<__DB> for User {
type SelectExpression = (users::r#id, users::r#name);
fn construct_selection() -> Self::SelectExpression {
(users::r#id, users::r#name)
}
}
fn _check_field_compatibility()
where
i32: diesel::deserialize::FromSqlRow<
diesel::dsl::SqlTypeOf<users::r#id>,
diesel::mysql::Mysql,
>,
String: diesel::deserialize::FromSqlRow<
diesel::dsl::SqlTypeOf<users::r#name>,
diesel::mysql::Mysql,
>,
{}
};
const _: () = {
use diesel;
use diesel::row::{Row as _, Field as _};
impl<
__DB: diesel::backend::Backend,
__ST0,
__ST1,
> diesel::deserialize::Queryable<(__ST0, __ST1), __DB> for User
where
(i32, String): diesel::deserialize::FromStaticSqlRow<(__ST0, __ST1), __DB>,
{
type Row = (i32, String);
fn build(row: (i32, String)) -> diesel::deserialize::Result<Self> {
use std::convert::TryInto;
Ok(Self {
id: row.0.try_into()?,
name: row.1.try_into()?,
})
}
}
};