Macro butane::filter

source ·
filter!() { /* proc-macro */ }
Expand description

Macro to construct a BoolExpr (for use with a Query) from an expression with Rust syntax.

Using this macro instead of constructing a BoolExpr has two advantages:

  1. It will generally be more ergonomic
  2. References to nonexistent fields or type mismatches (e.g. comparing a number to a string) will generate a compilation error

Usage: filter!(Foo, expr) where Foo is a model type (with the #[model] attribute applied) and expr is a Rust-like expression with a boolean value. Foo’s fields may be referred to as if they were variables.

Rust values

To refer to values from the surrounding rust function, enclose them in braces, like filter!(Foo, bar == {bar})

Function-like operations

Filters support some operations for which Rust does not have operators and which are instead represented syntactically as function calls.

  • like: parameter is a SQL LIKE expression string, e.g. `title.like(“M%”).
  • matches: Parameter is a sub-expression. Use with a ForeignKey field to evaluate as true if the referent matches. For example, to find all posts made in blogs by people named “Pete” we might say filter!(Post, blog.matches(author == “Pete”))`.
  • contains: Essentially the many-to-many version of matches. Parameter is a sub-expression. Use with a Many field to evaluate as true if one of the many referents matches the given expression. For example, in a blog post model with a field tags: Many<Tag> we could filter to posts with a “cats” with the following `tags.contains(tag == “cats”). If the expression is single literal, it is assumed to be used to match the primary key.

Examples

#[model]
struct Contestant {
  #[pk]
  name: String,
  rank: i32,
  nationality: String
}
let e: BoolExpr = filter!(Contestant, nationality == "US" && rank < 42);
let first_place = 1;
let e2 = filter!(Contestant, rank == { first_place });
let e3 = filter!(Contestant, name.like("A%"));