# `DrinkMeAlice.Ash.Filter`

Translate an Ash filter into a parameterized SurrealQL `WHERE` clause.

Supported: `and`/`or`/`not`, boolean literals, and — on a plain
attribute of the queried resource (no relationship path) compared with
a literal — `==`, `!=`, `>`, `>=`, `<`, `<=`, `in`, `is_nil`. Values
are encoded by the attribute's own type (`DrinkMeAlice.Ash.Codec`)
and always travel as bound params — never spliced into SQL text.

The primary key lives in the record id, so a reference to it becomes
`record::id(id)`.

Anything else is refused: `supported?/2` answers the data layer's
`can?(_, {:filter_expr, expr})`, so Ash reports an unsupported
filter before a query is built, and `to_where/3` returns
`{:error, {:unsupported_filter, _}}` as a second line of defence.
Nothing is ever evaluated client-side over an unbounded fetch.

# `supported?`

True when `expr` (one filter node) can be pushed down.

# `to_where`

```elixir
@spec to_where(Ash.Filter.t() | nil, atom(), binary()) ::
  {:ok, {binary(), map()}} | {:error, term()}
```

`{:ok, {where_sql, params}}` for a filter (`{"", %{}}` when there is
none), or `{:error, reason}`. `pk` is the primary-key attribute name;
`prefix` namespaces the generated param names.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
