[ 
https://issues.apache.org/jira/browse/SPARK-58418?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

ASF GitHub Bot updated SPARK-58418:
-----------------------------------
    Labels: pull-request-available  (was: )

> SCD2 AutoCDC fails with NUM_COLUMNS_MISMATCH when a flow narrower than the 
> evolved target reconciles
> ----------------------------------------------------------------------------------------------------
>
>                 Key: SPARK-58418
>                 URL: https://issues.apache.org/jira/browse/SPARK-58418
>             Project: Spark
>          Issue Type: Sub-task
>          Components: SQL
>    Affects Versions: 5.0.0
>            Reporter: Andreas Neumann
>            Priority: Major
>              Labels: pull-request-available
>
> h2. Summary
> SCD Type 2 AutoCDC flows fail on every microbatch when the flow's microbatch 
> is _narrower_ than the target table it writes to (i.e. the target was 
> schema-evolved wider by an earlier, wider run). The failure is 
> {{NUM_COLUMNS_MISMATCH}} for a dropped top-level column and 
> {{INCOMPATIBLE_COLUMN_TYPE}} for a dropped nested struct / array-element 
> field. SCD Type 1 is unaffected.
> h2. Mechanism
> To reconcile an incoming microbatch against existing history, 
> {{Scd2ForeachBatchHandler.reconcileMicrobatch}} reads back the 
> potentially-affected rows from both the auxiliary table and the target table 
> and unions them with the microbatch into a single dataframe:
> {code:scala}
> val microbatchAndAffectedRows = preprocessedBatchDf
>   .unionByName(affectedRowsFromAuxiliaryTable)
>   .unionByName(affectedRowsFromTargetTable)
> {code}
> These are plain {{unionByName}} calls with no {{allowMissingColumns = true}}. 
> {{unionByName}} requires all inputs to have the same set of columns, so the 
> union fails as soon as the microbatch's column set diverges from what is 
> stored in the target/aux tables.
> h2. When the column sets diverge
> They diverge whenever the target has been schema-evolved to be wider than the 
> current microbatch:
> * *Dropped top-level column* (or a narrowed {{COLUMNS}} selection): the 
> target still carries the column from an earlier wider run, but the new 
> microbatch does not produce it. The microbatch has N columns and the affected 
> target rows have N+1 -> {{NUM_COLUMNS_MISMATCH}}.
> * *Dropped nested struct / array-element field*: same column count, but the 
> struct types differ (the target's struct has field {{b.c}}, the microbatch's 
> does not), so the union fails with {{INCOMPATIBLE_COLUMN_TYPE}}.
> h2. Why SCD1 is not affected
> SCD1 never unions the microbatch with existing target rows. 
> {{Scd1ForeachBatchHandler}} reconciles the microbatch on its own and then 
> issues a SQL {{MERGE}} onto the target. A {{MERGE}} tolerates a source 
> narrower than the target: unmentioned columns are left untouched on 
> {{UPDATE}} and set to {{NULL}} on {{INSERT}}. So the identical "narrow the 
> flow after the target has grown" scenario works under SCD1.
> h2. Why it matters
> This is a realistic, user-facing path -- it is exactly what cross-run schema 
> evolution looks like:
> # Run a wide flow (target gains {{email}}).
> # Later run a narrower flow, or drop a source column, or tighten {{COLUMNS}}.
> # The SCD2 stream then dies on every microbatch until a full refresh.
> Schema evolution is meant to be additive-tolerant (existing rows keep their 
> old columns; a flow can stop emitting one), and SCD1 honors that. SCD2 breaks 
> it.
> h2. Likely fix
> Pass {{allowMissingColumns = true}} to those {{unionByName}} calls so a 
> narrower microbatch is padded with {{NULL}} for the columns it no longer 
> produces, matching SCD1's {{MERGE}} semantics. This needs care around the 
> nested-field case (union with missing nested fields) and around ensuring 
> downstream reconciliation treats the {{NULL}}-padded columns correctly.
> h2. Test coverage
> Discovered while writing the SCD2 end-to-end suites (SPARK-58409). Those 
> suites currently assert the actual failure and reference this ticket, so the 
> assertions can be flipped to the additive-preserving expectations once this 
> is fixed:
> * {{AutoCdcScd2MultiPipelineSuite}} -- stops short of re-running the narrower 
> pipeline against the widened target.
> * {{AutoCdcScd2SchemaEvolutionSuite}} -- has explicit tests asserting the 
> current {{NUM_COLUMNS_MISMATCH}} / {{INCOMPATIBLE_COLUMN_TYPE}} failures.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

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

Reply via email to