Commit 408dad3
Add MERGE INTO types to datafusion-expr (#20763)
## Which issue does this PR close?
- part of #20746
[EPIC] Complete DML Support (MERGE, INSERT OVERWRITE, TRUNCATE) #19617
As well as task 1 of #20746
## Rationale for this change
Lay the foundation for MERGE INTO support in DataFusion by adding the
logical plan types and their proto serialization. Keeping types separate
from execution lets reviewers reason about the data model independently
of the planner and physical dispatch.
## What changes are included in this PR?
**`datafusion/expr` — new types in `dml.rs`**
- `MergeIntoOp` — carries the `ON` join condition and ordered list of
`WHEN` clauses
- `MergeIntoClause` — a single `WHEN` clause: kind + optional predicate
+ action
- `MergeIntoClauseKind` — `Matched` / `NotMatched` /
`NotMatchedByTarget` / `NotMatchedBySource`; includes
`is_not_matched_by_target()` and `canonical()` helpers because
`NotMatched` and `NotMatchedByTarget` are semantically identical and
must be treated identically downstream
- `MergeIntoAction` — `Update(Vec<(col, expr)>)` / `Insert { columns,
values }` / `Delete`
- `WriteOp::MergeInto(MergeIntoOp)` variant added to the existing
`WriteOp` enum; `WriteOp` is now `#[non_exhaustive]` so future variant
additions are not a SemVer break
**`datafusion/proto-models` — proto schema**
- Extended `DmlNode` with a `MERGE_INTO` type tag and a boxed
`MergeIntoOpNode` payload field
- Added `MergeIntoOpNode`, `MergeIntoClauseNode`, `MergeIntoActionNode`
messages
**`datafusion/proto` — serialization**
- `from_proto`: `parse_write_op(&DmlNode, ...)` reads the payload when
the type tag is `MergeInto`; defensive helpers
`parse_merge_into_op/clause/action` with explicit errors for missing
fields
- `to_proto`: `serialize_merge_into_op/clause/action` helpers; encode
path uses an explicit `match` over all `WriteOp` variants producing
`(dml_type, merge_into)` pair — no silent payload loss
- Cross-crate conversions use `FromProto` (the crate-local trait) rather
than `From` to satisfy the Rust orphan rule after the upstream
`datafusion-proto-models` refactor
**Proto codegen** — after editing `.proto` files, regenerate with:
```bash
PROTOC=/tmp/protoc cargo run --manifest-path datafusion/proto-models/gen/Cargo.toml
```
(Install `protoc` from
https://github.com/protocolbuffers/protobuf/releases if not present; set
`PROTOC` to its path.)
## Are these changes tested?
- `datafusion-expr` unit tests: `WriteOp::MergeInto` display,
`is_not_matched_by_target`, `canonical`
- `datafusion-proto` round-trip test: exercises all four
`MergeIntoClauseKind` variants and all three `MergeIntoAction` variants
through encode → decode
- `datafusion-proto` error-path tests: missing `merge_into` payload,
missing `on` expression, unknown clause kind tag, missing clause action,
missing action oneof
## Are there any user-facing changes?
`WriteOp` gains a `MergeInto` variant and is now `#[non_exhaustive]`.
Existing downstream `match` arms need a wildcard arm added (this is
intentional and expected for a new DML operation).
## Follow-up
A stacking PR that adds the SQL planner, physical planner dispatch, and
`TableProvider::merge_into` hook is available at
wirybeaver#2. If reviewers prefer to
review both together in one pass, I'm happy to include that work here
instead.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent d5f03d9 commit 408dad3
9 files changed
Lines changed: 1571 additions & 33 deletions
File tree
- datafusion
- expr/src/logical_plan
- proto-models
- proto
- src/generated
- proto
- src/logical_plan
- tests/cases
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
28 | | - | |
| 28 | + | |
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| |||
227 | 227 | | |
228 | 228 | | |
229 | 229 | | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
230 | 233 | | |
| 234 | + | |
231 | 235 | | |
232 | 236 | | |
233 | 237 | | |
| |||
239 | 243 | | |
240 | 244 | | |
241 | 245 | | |
| 246 | + | |
| 247 | + | |
242 | 248 | | |
243 | 249 | | |
244 | 250 | | |
| |||
250 | 256 | | |
251 | 257 | | |
252 | 258 | | |
| 259 | + | |
253 | 260 | | |
254 | 261 | | |
255 | 262 | | |
| |||
291 | 298 | | |
292 | 299 | | |
293 | 300 | | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
294 | 391 | | |
295 | 392 | | |
296 | 393 | | |
297 | 394 | | |
298 | 395 | | |
299 | 396 | | |
300 | 397 | | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
39 | | - | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
40 | 43 | | |
41 | 44 | | |
42 | 45 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
311 | 311 | | |
312 | 312 | | |
313 | 313 | | |
| 314 | + | |
314 | 315 | | |
315 | 316 | | |
316 | 317 | | |
317 | 318 | | |
318 | 319 | | |
| 320 | + | |
| 321 | + | |
319 | 322 | | |
320 | 323 | | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
321 | 371 | | |
322 | 372 | | |
323 | 373 | | |
| |||
0 commit comments