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.
Summary
Types
@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() }