fix(datafusion): map column-less MERGE INSERT VALUES by position - #984
jackylee-ch wants to merge 2 commits into
Conversation
0db0c22 to
bdde90b
Compare
|
Requirement fit: SUPPORTED — retaining positional MERGE INSERT values fixes a real data-correctness issue. Implementation: FINDINGS at [P2] Validate positional INSERT arity before executing MERGE ( I reproduced this through SQL in both modes with a three-column Verification: 15/15 MERGE module tests and 29/29 MERGE SQL integration tests passed. The temporary invalid-arity SQL regression failed in both CoW and data-evolution mode with a successful commit. Diff check and current-main merge-tree passed; all 14 head CI checks are green. Temporary edits were restored. |
`WHEN NOT MATCHED THEN INSERT VALUES (s.a, s.b, ...)` without an explicit column list built an empty column->expression map, so `insert_select_clause` emitted `NULL` for every target column and dropped the source values. The merge then inserted all-NULL rows (or failed on a non-null column) instead of the source data — silent corruption for a column-less positional INSERT, which is valid standard SQL (the MERGE INSERT column list is optional) and accepted by DataFusion's parser. Map the VALUES to the table's columns by position when no column list is given, and reject a value/column count mismatch. Explicit-column and `INSERT *` clauses are unchanged. Added an end-to-end MERGE test using a column-less INSERT; it inserts all-NULL rows before the fix.
The value-count check for a column-less positional INSERT lived in `insert_select_clause`, which only runs while building unmatched-row batches. A fully matched CoW merge (and the data-evolution empty-batch path) skips that step, so an invalid `INSERT VALUES (s.a, s.b)` against a three-column target was accepted and the matched UPDATE committed. Move the arity check into `validate_merge_insert_columns`, which both execute paths call before any batch is built. `INSERT *`/`INSERT ROW` (no columns and no values) is unaffected. Added a regression: an all-matched MERGE with a short positional INSERT now fails without changing the target.
bdde90b to
8178f94
Compare
|
Addressed. The positional value-count check moved from Regression Rebased onto current main. The |
WHEN NOT MATCHED THEN INSERT VALUES (s.a, s.b, ...)without an explicit column list built an empty column->expression map, soinsert_select_clauseemittedNULLfor every target column and dropped the source values. The merge then inserted all-NULL rows (or failed on a non-null column) instead of the source data — silent corruption for a column-less positional INSERT. This form is valid standard SQL (the MERGE INSERT column list is optional) and DataFusion's parser accepts it; Spark's own MERGE grammar, by contrast, requires an explicit column list orINSERT *. The existing MERGE INSERT tests all pass an explicit column list, so this went uncovered.Map the VALUES to the table's columns by position when no column list is given, and reject a value/column count mismatch. Explicit-column and
INSERT *clauses are unchanged.Added an end-to-end MERGE test using a column-less INSERT; it inserts all-NULL rows before the fix.