rustrust-diesel

What is a short and concise type for predicates


I'd like to be able to keep predicates for filtering my tables somewhere in one place and give them nice names. E.g.: instead of writing something like

let post = posts
    .filter(published.eq(true).and(id.eq(5))
    ...

I'd like to have a function like this:

fn published_with_id(n: i64) -> (WHAT HERE?) {
    published.eq(true).and(id.eq(n))
}
...
let post = posts.filter(published_with_id(5))

However, when I try to compile that code, I get a suggestion to declare the return type of the predicate function as something long and with something quite long indeed: diesel::expression::grouped::Grouped<diesel::expression::operators::And<diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<columns::published, diesel::expression::bound::Bound<diesel::sql_types::Bool, bool>>>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<columns::id, i64>>>>

Is there a way to annotate it with a reasonable return type? Or is there a better way to keep all my predicates in one place?


Solution

  • There is a way to specify that a function returns something implementing a trait, without naming a concrete type. It's called return position impl trait (RPIT), and lucky for you you have a common trait, as all query builder combinators defined in diesel::expression implement Expression. So the solution is to use impl Expression as the return type:

    fn published_with_id(n: i64) -> impl Expression {
        published.eq(true).and(id.eq(n))
    }