Mutare.Ecto.Clause (mutare_ecto v0.1.0)

Copy Markdown View Source

Standalone/pipe clause-macro mutations — the composable cousins of the whole-from family in Mutare.Ecto.Query. Where Query mutates from's keyword clauses, this mutates the same kinds of thing written as standalone calls or pipe stages:

  • Orderingorder_by(q, [u], asc: u.name) / q |> order_by(asc: u.name): flip a sort direction (:asc:desc, nulls-placement variants), via the shared Mutare.Ecto.Ordering catalog.
  • Aggregateselect(q, [u], sum(u.amount)) / q |> select_merge(%{n: max(u.x)}), and an aggregate written into an order_by (q |> order_by([u], desc: sum(u.amount))): swap the aggregate (sumavg, minmax), via the shared Mutare.Ecto.Aggregate walker. (A having aggregate is hosted instead — Mutare.Ecto.Host.)
  • Scalarselect(q, [u], u.price * u.qty) / q |> order_by([u], desc: u.a + u.b) / q |> select([u], coalesce(u.score, 0)): mutate a value-computing form via the shared Mutare.Ecto.Scalar catalog — the arithmetic swaps (+-, */) and the coalesce fallback drop. (The same forms in a where/having condition are hosted instead.)
  • Combinationq |> intersect(^other) / except_all(q, ^other): swap the set operation by renaming the macro itself (intersectexcept, intersect_allexcept_all), via the shared Mutare.Ecto.Combination catalog. Unlike the others this mutates the call's name, not its last argument — the operand queries are untouched.

These macros route through the :routing classifier (Mutare.Ecto.Host.Routing), which keeps their data positions raw while the routed node is still offered whole to mutate/2; the mutation rides Mutare's ordinary in-place selector, since the macro call is itself an expression. The orthogonal stage removal (q |> order_by(…)q) lives in Mutare.Ecto.ClauseDrop, and the :bound ±1 bump of a literal limit/offset is hosted pin-only (Mutare.Ecto.Bound; NOTES "Bound bump: from whole-call rewrite to pin-only hosting").

The mutated position is always the last argument (the ordering / the selector), which is true for both the direct form (order_by(q, binds, ordering)) and the pipe form (q |> order_by(binds, ordering), where q is the piped left side, not in args) — so no pipe-mode bookkeeping is required.

Summary

Functions

Standalone/pipe clause-macro mutations for node as self-tagging Mutare.Ecto.Tags (a swap family — order/aggregate — carries the finer operator/kind label), or [].

Functions

mutations(call, context)

@spec mutations(Mutare.Ecto.AST.QueryCall.t(), Mutare.Ecto.Context.t()) :: [
  Mutare.Ecto.SubMutator.tagged()
]

Standalone/pipe clause-macro mutations for node as self-tagging Mutare.Ecto.Tags (a swap family — order/aggregate — carries the finer operator/kind label), or [].