# `Mutare.Ecto.StaticCondition`
[🔗](https://github.com/foxbenjaminfox/mutare_ecto/blob/v0.4.2/lib/mutare/ecto/static_condition.ex#L1)

The condition the host cannot weave, and its whole-call delivery.

The host delivers a hosted condition's mutants by weaving: the condition becomes a
`^`-pinned `dynamic/2` that re-declares the condition's bindings (`Mutare.Ecto.Host`). Some
conditions cannot take that form, though each is valid as written.

**A subquery in a `having`.** Weaving changes how Ecto builds the clause — from the
compile-time filter builder to the runtime dynamic path — and the two do not accept the same
expressions:

    from p in "posts",
      group_by: p.user_id,
      having: count(p.id) > subquery(from t in "thresholds", select: max(t.value))

Written statically this is valid; as `having: ^dynamic([p], …)` Ecto raises "subqueries are
not allowed in `having` expressions". It raises when the query is **built**, not when the
module compiles, and it raises on the woven *original* branch as readily as on a mutant — so
weaving it would break the unmutated code path of every test that reaches the function.

**A binding declaration the plugin cannot re-declare** — a computed index (`[{p, index}]`) or
an interpolated name that calls a function (`[{^name(), p}]`), each of which a re-declaration
would evaluate a second time (`Mutare.Ecto.Host.Bindings`). The woven `dynamic/2` has no
faithful binding list to carry, and an empty one would leave the condition's variables
unbound. A condition that is itself a `^` pin is the exception: it is woven pin-only, with no
`dynamic/2` and so no bindings (`Mutare.Ecto.Host.Target`'s root-pin rule), whatever the
declaration.

**Repeated explicit `on:` predicates.** Ecto combines these before escaping the join's
condition, so each written predicate must be rebuilt statically. A sole explicit predicate
on an association join can weave: Ecto attaches association constraints later, in planning.

**A filter that is, or may become, the literal `true`.** Ecto's runtime filter path discards a
`where`/`having` condition that expands to `true`, whatever its operator
(`Ecto.Query.Builder.Filter.apply/3`); the static build keeps it. Alone that loses nothing, but
`where: false, or_where: true` becomes `where: false`, and `where: true, or_where: p.x > 1`
becomes `where: p.x > 1`. A woven branch that is the literal `true` is lost the same way,
whether it is the original (baseline rows change) or a mutant (`or_where: coalesce(true, x)`
→ `true` delivers another query than it reports). So a filter condition is rebuilt when it,
or a mutant of the plugin's own catalog, is the literal `true`, read through the `filter/1`
that Ecto's escape erases (`filter(true)`). A pin's mutants cannot be:
they keep the pin. A join's `on:` keeps a `true` on both paths.

**A condition typed by its clause.** The static builder escapes a condition as `:boolean`, the
dynamic one as `:any`, and the type reaches whatever the condition passes it on to:
`coalesce`'s operands, arithmetic operands, a unary minus. A pin there is cast by that type
(`where: coalesce(^"true", false)` binds `true` statically and the string `"true"` in a
dynamic, which SQLite reads as false), and a non-boolean literal there is tagged with it. So a
condition is rebuilt when a pin or a non-boolean literal takes the condition's own type, in the
condition or in a catalog mutant of it. A root pin is exempt: it is woven pin-only, never into
a `dynamic/2`, and Ecto builds it at runtime natively too.

**A fragment splice.** `fragment("? IN (?)", p.id, splice(^values))` writes one placeholder per
list element, each naming the one parameter the list is (`Ecto.Query.Builder.splice!/2`). The
static planner binds the list's elements once; the dynamic path appends the parameter at each
placeholder, so a woven `values = [1, 2]` binds four values to two placeholders and the
baseline fails. So a condition that splices is rebuilt.

**A call Ecto can only be expanding** (`Mutare.Ecto.Walk.opaque_call?/2`): an author macro,
registered or not, or a module attribute. Its expansion is escaped with the condition, and the
source does not show it: `member_sql(p.id, ^values)` may expand to the splice above, and
`over_threshold(p)` to a subquery the `having` rejects in a dynamic. So a condition holding one
is rebuilt, whatever the expansion turns out to be. A pin's interior and a subquery wrapper's
argument (`exists(from …)`) are not read: Ecto evaluates both as Elixir, apart from the
condition's escape, so a call there expands the same way on either path. An ignore directive
leaves delivery intact; it is not a baseline-safety switch.

## The rule

`delivery/5` applies the configured policy, rebuilds a filter that is or may become the literal
`true`, a condition typed by its clause, one that splices and one holding a call Ecto can
only be expanding (above), then `delivery/4` decides from the receiving
clause, the expression, its predicate kind, and the declaration it is read under. A condition is **rebuilt** when the
expression carries a subquery (`Mutare.Ecto.Subquery.present?/1`) that the clause rejects in a
dynamic (`Mutare.Ecto.Surface.dynamic_subqueries?/1` — everything but `where`/`or_where`), or when
it is not a `:root_pin` and its declaration does not read (`t:Mutare.Ecto.Host.Bindings.result/0`
is `:error`); every other condition is **woven**. Both the host and `mutations/2` enumerate the
same conditions (`Mutare.Ecto.Host.Condition`) and ask `delivery/5` of each, so each condition is
delivered once: woven, or rebuilt here.

Only a **predicate** is either's, and `Mutare.Ecto.Host.Condition` locates nothing else
(`Mutare.Ecto.Host.Condition.shape/1`). A keyword filter carries a subquery as readily
(`having: [score: subquery(…)]` — Ecto's filter builder accumulates a pair value's), and sits
under an unread declaration as readily, but the weave would carry nothing for it — its pairs
are routed to core one by one — so neither is this module's rebuild, which would otherwise
read the list as a predicate and rename its column keys.

## Delivery

Hosting is a delivery optimization, not a semantic category. The mutants are the ones the
weave would have carried — the plugin's own catalog (`Mutare.Ecto.Host.Catalog.own_catalog/2`)
and the `^`-pin interiors sub-contracted to core (`Mutare.Ecto.Island`) — each delivered as
the **whole call** rebuilt around one mutated condition, through Mutare's ordinary in-place
selector (the delivery `Mutare.Ecto.Dynamic` and `Mutare.Ecto.Query` use). Every selector
branch is then a statically built clause under the written declaration, which Ecto accepts. A
catalog mutant still reports at the expression it changed (`Mutare.Ecto.Walk` anchors it); a
pin-interior mutant reports at the whole call, as it does from `Mutare.Ecto.Dynamic`. The
`families:` filter and equivalence notes apply as on any `mutate/2` path.

The subquery rule follows Ecto's current behaviour without depending on it: were a later Ecto
to accept the dynamic form, this delivery would remain valid, only more verbose than the weave.

# `delivery`

```elixir
@type delivery() :: {:woven, bindings :: [Macro.t()]} | :rebuilt
```

How one hosted condition's mutants are delivered — see `delivery/4`.

# `receiver`

```elixir
@type receiver() ::
  Mutare.Ecto.Host.JoinOn.receiver()
  | {:static_from, Mutare.Ecto.Host.JoinOn.receiver()}
```

The clause receiving a condition (`Mutare.Ecto.Host.JoinOn.receiver/0`), or, as
`{:static_from, receiver}`, one in a `from` that holds a filter Ecto's runtime path discards
(`from_receiver/3`).

# `delivery`

```elixir
@spec delivery(
  receiver(),
  Macro.t(),
  Mutare.Ecto.Host.Condition.predicate_kind(),
  Mutare.Ecto.Host.Bindings.result()
) :: delivery()
```

How the host delivers `condition`, a predicate of `kind` (`Mutare.Ecto.Host.Condition.shape/1`)
received by `clause` (a condition macro's name, a `from` clause key, or `:on`) under the
declaration `bindings` reads as: `{:woven, list}`, carrying the binding list the woven
`dynamic/2` re-declares (none for a `:root_pin`, which is woven without one), or `:rebuilt`, by
`mutations/2` — see "The rule" in the moduledoc.

# `delivery`

```elixir
@spec delivery(
  receiver(),
  Macro.t(),
  Mutare.Ecto.Host.Condition.predicate_kind(),
  Mutare.Ecto.Host.Bindings.result(),
  Mutare.Ecto.Config.t()
) :: delivery()
```

Apply the configured delivery policy before considering automatic hosting.

# `from_receiver`

```elixir
@spec from_receiver(atom(), Mutare.Ecto.AST.KeywordList.t(), non_neg_integer()) ::
  receiver()
```

The receiver of the condition at `index` of a `from`'s `clauses`. A `from` is built
statically only up to its first runtime clause, and a woven condition is one: every clause
after it is applied at runtime, where Ecto's filter builder discards a filter that is the
literal `true` (see "A filter that is, or may become, the literal `true`"). So a condition
followed by a filter that is, or may expand to, the literal `true` (or `[]`, which Ecto
escapes to it) is rebuilt.

# `mutations`

```elixir
@spec mutations(Mutare.Ecto.AST.QueryCall.t(), Mutare.Ecto.Context.t()) :: [
  Mutare.Ecto.SubMutator.tagged() | Mutare.Mutator.Mutation.t()
]
```

Every single-point mutant of each hosted condition in `call` that `delivery/4` rebuilds, as
the **whole call** rebuilt around the mutated condition — a condition macro
(`having(q, [p], …)`, direct or piped), a standalone `join`'s `on:`, or a `from`'s keyword
clauses. `[]` for a call with no such condition, which is nearly every call.

# `weavable?`

```elixir
@spec weavable?(atom(), Macro.t()) :: boolean()
```

The half of `delivery/4` read off the clause and the expression alone: whether `clause`
accepts `condition` as a `^`-pinned `dynamic/2` — false only for a subquery in a clause that
rejects a dynamic one.

---

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