pub trait BoxableExpression<QS, DB, GB = (), IsAggregate = No>{ }Expand description
Helper trait used when boxing expressions.
In Rust you cannot create a trait object with more than one trait.
This type has all of the additional traits you would want when using
Box<Expression> as a single trait object.
By default BoxableExpression is not usable in queries that have a custom
group by clause. Setting the generic parameters GB and IsAggregate allows
to configure the expression to be used with a specific group by clause.
This is typically used as the return type of a function. For cases where you want to dynamically construct a query, boxing the query is usually more ergonomic.
§Examples
§Usage without group by clause
use diesel::sql_types::Bool;
enum Search {
    Id(i32),
    Name(String),
}
type DB = diesel::sqlite::Sqlite;
fn find_user(search: Search) -> Box<dyn BoxableExpression<users::table, DB, SqlType = Bool>> {
    match search {
        Search::Id(id) => Box::new(users::id.eq(id)),
        Search::Name(name) => Box::new(users::name.eq(name)),
    }
}
let user_one = users::table
    .filter(find_user(Search::Id(1)))
    .first(conn)?;
assert_eq!((1, String::from("Sean")), user_one);
let tess = users::table
    .filter(find_user(Search::Name("Tess".into())))
    .first(conn)?;
assert_eq!((2, String::from("Tess")), tess);§Allow usage with group by clause
use diesel::sql_types::Text;
use diesel::dsl;
use diesel::expression::ValidGrouping;
enum NameOrConst {
    Name,
    Const(String),
}
type DB = diesel::sqlite::Sqlite;
fn selection<GB>(
    selection: NameOrConst
) -> Box<
    dyn BoxableExpression<
        users::table,
        DB,
        GB,
        <users::name as ValidGrouping<GB>>::IsAggregate,
        SqlType = Text
    >
>
where
    users::name: BoxableExpression<
            users::table,
            DB,
            GB,
            <users::name as ValidGrouping<GB>>::IsAggregate,
            SqlType = Text
        > + ValidGrouping<GB>,
{
    match selection {
        NameOrConst::Name => Box::new(users::name),
        NameOrConst::Const(name) => Box::new(name.into_sql::<Text>()),
    }
}
let user_one = users::table
    .select(selection(NameOrConst::Name))
    .first::<String>(conn)?;
assert_eq!(String::from("Sean"), user_one);
let with_name = users::table
    .group_by(users::name)
    .select(selection(NameOrConst::Const("Jane Doe".into())))
    .first::<String>(conn)?;
assert_eq!(String::from("Jane Doe"), with_name);§More advanced query source
This example is a bit contrived, but in general, if you want to for example filter based on
different criteria on a joined table, you can use InnerJoinQuerySource and
LeftJoinQuerySource in the QS parameter of BoxableExpression.
use diesel::sql_types::Bool;
use diesel::dsl::InnerJoinQuerySource;
enum UserPostFilter {
    User(i32),
    Post(i32),
}
type DB = diesel::sqlite::Sqlite;
fn filter_user_posts(
    filter: UserPostFilter,
) -> Box<dyn BoxableExpression<InnerJoinQuerySource<users::table, posts::table>, DB, SqlType = Bool>>
{
    match filter {
        UserPostFilter::User(user_id) => Box::new(users::id.eq(user_id)),
        UserPostFilter::Post(post_id) => Box::new(posts::id.eq(post_id)),
    }
}
let post_by_user_one = users::table
    .inner_join(posts::table)
    .filter(filter_user_posts(UserPostFilter::User(2)))
    .select((posts::title, users::name))
    .first::<(String, String)>(conn)?;
assert_eq!(
    ("My first post too".to_string(), "Tess".to_string()),
    post_by_user_one
);Trait Implementations§
Source§impl<QS, ST, DB, GB, IsAggregate> QueryId for dyn BoxableExpression<QS, DB, GB, IsAggregate, SqlType = ST> + '_
 
impl<QS, ST, DB, GB, IsAggregate> QueryId for dyn BoxableExpression<QS, DB, GB, IsAggregate, SqlType = ST> + '_
Source§const HAS_STATIC_QUERY_ID: bool = false
 
const HAS_STATIC_QUERY_ID: bool = false
Self be uniquely identified by its type? Read more