# `Latu.MergeInto`
[🔗](https://github.com/zero-one-group/latu/blob/v0.4.0/lib/latu/merge_into.ex#L1)

A merge being assembled: a source frame, a target table, and the clauses to apply.

`MergeIntoTableCommand` carries three lists of actions, so a merge is built up before it is
sent — the same client-side fiction as `Latu.GroupedData`, and inert data in the same way.
PySpark spells it as a two-level fluent builder (`whenMatched(cond).update({...})`), which
needs an object per clause; here each clause is one call that says both what it matches and
what it does.

    source
    |> Latu.as("s")
    |> Latu.merge_into("people", expr("people.id = s.id"))
    |> Latu.when_matched(:update, set: [name: col("s.name")])
    |> Latu.when_not_matched(:insert_all)
    |> Latu.merge()

Nothing reaches the server until `Latu.merge/2`, so a half-built merge can be passed around,
stored, or extended in a pipeline like any other value.

# `t`

```elixir
@type t() :: %Latu.MergeInto{
  condition: Latu.Plan.expression(),
  matched: [Latu.Plan.expression()],
  not_matched: [Latu.Plan.expression()],
  not_matched_by_source: [Latu.Plan.expression()],
  schema_evolution: boolean(),
  source: Latu.DataFrame.t(),
  table: String.t() | atom()
}
```

# `when_matched`

```elixir
@spec when_matched(t(), atom(), keyword()) :: t()
```

See `Latu.when_matched/3`.

# `when_not_matched`

```elixir
@spec when_not_matched(t(), atom(), keyword()) :: t()
```

See `Latu.when_not_matched/3`.

# `when_not_matched_by_source`

```elixir
@spec when_not_matched_by_source(t(), atom(), keyword()) :: t()
```

See `Latu.when_not_matched_by_source/3`.

---

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