Mutare.Ecto.Host.Routing (mutare_ecto v0.2.1)

Copy Markdown View Source

Classifies arguments of registered query macros for Mutare.CallRouting.route_arguments/2. Core follows these routes; Mutare.Ecto.Host supplies the targets at :hosted positions.

Query sources

The call's form determines where its query source is: the first visible argument when direct, or Mutare.CallRouting.Call.pipe_left when piped. The source's shape then determines its treatment, identically for from and the composable where/join/limit stages:

  • A schema alias, table-name string (including interpolation), or {"table", Schema} pair stays :raw. Replacing a table/schema name makes a broken query.
  • An in binding declaration stays :raw. It is syntax the macro consumes, not an Elixir expression. This also withholds mutations inside its queryable (p in build(n + 1)); the host separately reads the declaration through Mutare.Ecto.Host.Bindings.
  • A fragment(...) source stays :raw: its template and arguments are SQL syntax.
  • A values(rows, types) source stays :raw: its row keys and declared SQL types describe the source's structure and must agree.
  • Every other source routes :expression: a variable, function call, nested from, or upstream pipeline. Core keeps its mutations reachable through the enclosing query stage.

No shape guess locates the source, and no call resolution inside a piped source is needed: pipe_left contains the source as written, before core resolves its calls.

Query data

  • from routes its clause list per pair. Expression conditions (where/having/on) route :hosted; keyword-shorthand conditions route their scalar values :interpolated. Literal limit:/offset: values route :hosted for the pin-only bound bumps. Other clause values stay raw for the whole-from producers. Mutare.Ecto.AST.FromCall places the clauses and reads the source in both spellings. Core preserves a piped binding declaration as syntax in each whole-call mutant branch.
  • Composable conditions locate their condition through Mutare.Ecto.Host.Condition. A predicate routes :hosted; a keyword shorthand routes per pair, exactly as in from. Written binding lists stay raw.
  • Plain clauses (select/order_by/…) keep their data raw. A literal-integer bound (limit/offset) instead routes :hosted, using Mutare.Ecto.Bound's literal-only guard.
  • join routes its trailing options per pair: on: uses the condition classification, while as:/prefix:/hints: stay raw.

A shorthand routes scalar values through ^ interpolation because Ecto rejects a bare selector case there. Keys, nil values (IS NULL, never = nil), existing pins and compound values stay raw. Those scalar mutants belong to core's producing family, not :ecto. Mutare.Ecto.Host.Condition decides whether a value is a predicate or shorthand once, so the host and classifier agree even when a sibling position causes the whole call to be hosted.

:hosted permits the host to consider a position; it does not promise the host will weave it. Declaration and receiving-clause constraints remain Mutare.Ecto.StaticCondition's. Whole nodes are still offered to the plugin's mutators regardless of their argument routes.

dynamic and is_named_binding register :raw instead of using this classifier (Mutare.Ecto.Surface.macro_registrations/0): neither threads a query. A free-standing dynamic is still offered whole to Mutare.Ecto.Dynamic.

Summary

Functions

Route the visible arguments and, when piped, the source carried in call.pipe_left. Both source positions use the same shape classifier.

Per-visible-argument treatments for a registered query macro. pipe_left places the source by the call's written form, and supplies its AST when it is outside the visible arguments. Returns [] for a name the plugin doesn't route.

Functions

route_arguments(call, context)

Route the visible arguments and, when piped, the source carried in call.pipe_left. Both source positions use the same shape classifier.

treatments(macro, args, pipe_left)

Per-visible-argument treatments for a registered query macro. pipe_left places the source by the call's written form, and supplies its AST when it is outside the visible arguments. Returns [] for a name the plugin doesn't route.