anew opened a new pull request, #57669:
URL: https://github.com/apache/spark/pull/57669

   ### What changes were proposed in this pull request?
     
   `Scd2ForeachBatchHandler.reconcileMicrobatch` unions the incoming microbatch 
with the affected auxiliary- and target-table rows in order to reconcile SCD 
Type 2 history. Those two unions used plain `unionByName`, which requires all 
inputs to have an identical column set:
     
     ```scala
     val microbatchAndAffectedRows = preprocessedBatchDf
       .unionByName(affectedRowsFromAuxiliaryTable)
       .unionByName(affectedRowsFromTargetTable)
     ```
     
   After cross-run schema evolution, the target table (and the auxiliary table, 
whose schema mirrors it) can carry user columns that the current microbatch no 
longer emits — a dropped source column, a narrowed `COLUMNS` selection, or a 
dropped nested struct/array field. The microbatch is then *narrower* than the 
affected rows, and the union fails.
     
   This passes `allowMissingColumns = true` to both unions, so a narrower 
microbatch is padded with `null` for the columns it no longer emits (recursing 
into structs and arrays; map types are not supported by `unionByName`, a 
documented limitation).
     
   ### Why are the changes needed?
     
   Before this change, an SCD2 AutoCDC stream fails on **every** microbatch 
once a flow becomes narrower than its evolved target:
     
     - dropped top-level column / narrowed `COLUMNS` selection → 
`NUM_COLUMNS_MISMATCH`
     - dropped nested struct or array-element field → `INCOMPATIBLE_COLUMN_TYPE`
     
   SCD Type 1 does not have this problem because it `MERGE`s the microbatch 
onto the target rather than unioning it with existing rows, and a `MERGE` 
tolerates a source narrower than the target. SCD2 should match that 
additive-tolerant behavior so column-schema evolution works without a full 
refresh.
     
   Records already written to the target keep their values: the target-table 
`MERGE`'s `UPDATE` assignments draw from the affected target rows, not from the 
null-padded microbatch rows, so only records *opened* by the narrower 
microbatch carry `null` for the no-longer-emitted column — the same semantics 
SCD1 gives.
     
   Note: this covers column-schema evolution that leaves the effective 
tracked-history column set unchanged. Changing the tracked-history set is a 
distinct concern with different correctness implications and is scoped 
separately under SPARK-58452 - and initially will require a full-refresh under 
SPARK-58391.
     
   ### Does this PR introduce _any_ user-facing change?
     
   Yes. An SCD2 AutoCDC flow whose microbatch is narrower than its 
already-evolved target now reconciles correctly instead of failing the stream 
with `NUM_COLUMNS_MISMATCH` / `INCOMPATIBLE_COLUMN_TYPE`. Columns dropped from 
the flow are preserved on records already written and are `null` on records 
opened after the drop. This is within the unreleased AutoCDC feature on master.
     
   ### How was this patch tested?
     
   New `AutoCdcScd2ColumnEvolutionSuite` (4 end-to-end tests):
     - a source column dropped between runs — preserved on existing records, 
`null` on new ones;
     - the `COLUMNS` selection narrowed between runs — same contract;
     - a late narrower event that bisects existing history — pre-existing 
records keep their values, only the new record carries `null`;
     - a nested struct field dropped between runs — preserved on existing 
records, `null` on new ones.
     
   ### Was this patch authored or co-authored using generative AI tooling?
     
   Generated-by: Claude Code (Opus 4.8)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to