Standalone/pipe clause-macro mutations — the composable counterparts 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:
- Ordering —
order_by(q, [u], asc: u.name)/q |> order_by(asc: u.name): flip a sort direction (:asc↔:desc, nulls-placement variants), via the sharedMutare.Ecto.Orderingcatalog. - Aggregate —
select(q, [u], sum(u.amount))/q |> select_merge(%{n: max(u.x)}), and an aggregate written into anorder_by(q |> order_by([u], desc: sum(u.amount))): swap the aggregate (sum↔avg,min↔max), via the sharedMutare.Ecto.Aggregatewalker. (Ahavingaggregate is hosted instead —Mutare.Ecto.Host.) - Scalar —
select(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 sharedMutare.Ecto.Scalarcatalog — the arithmetic swaps (+↔-,*↔/) and the coalesce fallback drop. (The same forms in awhere/havingcondition are hosted instead.) - Combination —
q |> intersect(^other)/except_all(q, ^other): swap the set operation by renaming the macro itself (intersect↔except,intersect_all↔except_all), via the sharedMutare.Ecto.Combinationcatalog. Unlike the others this mutates the call's name, not its last argument — the operand queries are untouched. - JoinType —
join(q, :left, [p], c in Comment, on: …)/q |> join(:full, …): narrow the join's kind by swapping its written qualifier (:left→:inner,:full→:left/:right, and:left↔:rightunder aRIGHT-capable dialect), via the sharedMutare.Ecto.JoinTypecatalog — the same flips, under the same policy anddialects:gate, asMutare.Ecto.Query'sleft_join:key swap. Only a literal qualifier is swapped: a computed one (join(q, kind, …)) is a value mutated where it is bound.
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 uses 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").
A value capability's mutated position is always the last argument (the ordering / the
selector), and the join qualifier the call's second argument. Both hold in the direct form
(order_by(q, binds, ordering)) and the pipe form (q |> order_by(binds, ordering)) alike,
since a pipe stage reaches the plugin as the direct call it is sugar for.
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 [].