Translates an Ash.Filter expression into a parameterized Cypher WHERE
fragment. Only operators ArcadeDB can push down are emitted; anything else
returns {:error, %UnsupportedFilter{}} carrying operator/field only (never the
value — AGENTS.md Rule 4).
Every value rides a bound $param (AshArcadic.Query.add_param/2); every
attribute name is validated as an Arcadic.Identifier first (R1 — the filter
side the AGE port left unvalidated). Range operators are rejected on
non-range-comparable storage (binary base64; :decimal exact-string, D27) so a
range filter fails LOUD, never lexicographically wrong.
Supported
eq · not_eq · gt · lt · gte · lte · in · is_nil · and · or · not ·
contains · string_starts_with · string_ends_with · literal true/false
(Ash lowers a no-match exists(rel, …) to a bare boolean) · a filter ON an
EXPRESSION calculation Ref (expanded to Cypher via AshArcadic.Query.Expression) ·
a raw compound value-expression comparison (a + b > 5, first <> last == "x")
Not supported (→ UnsupportedFilter)
like · ilike · attribute-to-attribute comparisons · a filter ON an AGGREGATE Ref or a MODULE (non-expression) calculation Ref (a COMPUTED value not Cypher-expressible — Finding A)
ArcadeDB CONTAINS/STARTS WITH/ENDS WITH are case-SENSITIVE; a :ci_string
attribute's case-insensitive semantics are not preserved (usage-rules).
Summary
Functions
Translate an Ash filter expression into a Cypher WHERE fragment + params.
Functions
@spec translate(term(), AshArcadic.Query.t()) :: {:ok, AshArcadic.Query.t(), String.t()} | {:error, term()}
Translate an Ash filter expression into a Cypher WHERE fragment + params.