[FLINK-39700][table-planner] Fix column-order sensitivity in validateAndExtractColumnChanges#28194
Merged
Merged
Conversation
Collaborator
d9aacab to
98cba84
Compare
…ation into AlterMaterializedTableChangeOperation Validation that was scattered across MaterializedTableChangeHandler (checkForChangedPositionByQuery, droppedPersistedCnt, validationErrors) and SqlAlterMaterializedTableDropSchemaConverter is consolidated into AlterMaterializedTableChangeOperation.validateChanges(). The handler becomes a pure applier: it throws immediately on unknown changes and applies DropColumn unconditionally. Same errors are thrown, just from the right layer. Tests for both layers (AlterMaterializedTableChangeOperationValidationTest, AlterMaterializedTableAsQueryOperationValidationTest, MaterializedTableChangeHandlerTest) are added alongside the prod change.
98cba84 to
c30a346
Compare
Contributor
Author
|
@flinkbot run azure |
b0aec94 to
c30a346
Compare
Contributor
Author
|
@flinkbot run azure |
f0b1bbe to
c30a346
Compare
Contributor
Author
|
@flinkbot run azure |
d2d729e to
c30a346
Compare
snuyanzin
reviewed
May 19, 2026
| List<Column> oldColumns, | ||
| Map<String, Integer> columnIndex, | ||
| List<String> errors) { | ||
| final Integer idx = columnIndex.get(change.getColumnName()); |
Contributor
There was a problem hiding this comment.
nit
Suggested change
| final Integer idx = columnIndex.get(change.getColumnName()); | |
| final int idx = columnIndex.getOrDefault(change.getColumnName(), -1); |
and then have logic similar to checkPositionChange
with
if (index < 0) {
return;
}
errors.add(
...
Contributor
There was a problem hiding this comment.
same for checkPhysicalTypeChange
c30a346 to
92c6b21
Compare
snuyanzin
reviewed
May 19, 2026
| } | ||
|
|
||
| @VisibleForTesting | ||
| public void validateChanges() { |
Contributor
There was a problem hiding this comment.
WDYT about movement public methods up, private to the bottom?
Contributor
Author
There was a problem hiding this comment.
Done, moved public methods up and private to the bottom.
…TER drops absent non-persisted columns validateAndExtractColumnChanges switches from position-based throws to name-based diff: columns are matched by name; new columns emit AddColumn; matched columns with type/class/comment differences emit ModifyPhysicalColumnType/ModifyColumn/ModifyColumnComment; absent columns emit DropColumn (skipping non-persisted when schemaDefinedInQuery=false). This allows physical DDL columns to be declared in a different order than the AS SELECT projection. AlterMaterializedTableChangeOperation gains a protected computeNewTable() hook so subclasses can plug in a different builder without shadowing the cached newTable field. FullAlterMaterializedTableOperation overrides the hook with a newTableBuilder lambda supplied by SqlCreateOrAlterMaterializedTableConverter so non-persisted columns absent from the new DDL are dropped (declarative CREATE OR ALTER semantics). Tests for validateAndExtractColumnChanges are added alongside.
92c6b21 to
f750378
Compare
Contributor
Author
|
@flinkbot run azure |
snuyanzin
approved these changes
May 20, 2026
Contributor
snuyanzin
left a comment
There was a problem hiding this comment.
LGTM
Thanks for addressing feedback
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is the purpose of the change
Physical DDL columns in
CREATE OR ALTER MATERIALIZED TABLEcould not be declared in a different order than theAS SELECTprojection, becausevalidateAndExtractColumnChangescompared old and new schemas positionally. This PR switches to name-based matching so that type changes, computed-column definition changes, drops, and additions each generate the appropriateTableChangeentry.It also consolidates query-change and persisted-column-drop validation — previously scattered across
MaterializedTableChangeHandlerandSqlAlterMaterializedTableDropSchemaConverter— intoAlterMaterializedTableChangeOperation.validateChanges(). The handler becomes a pure applier.CREATE OR ALTERnow uses declarative semantics: non-persisted columns absent from the explicit DDL are dropped instead of kept.Brief change log
MaterializedTableUtils.validateAndExtractColumnChanges: replace positional comparison with name-based lookup over all column kinds (physical, computed, metadata):ModifyPhysicalColumnType(instead of throwing)ModifyColumnModifyColumnComment(also emitted alongsideModifyPhysicalColumnTypewhen both change)DropColumn; non-persisted columns are skipped whenschemaDefinedInQuery=false(schema derived from query projection, so absent non-persisted columns are assumed to still exist rather than being intentionally removed)AddColumn; nullable coercion applied whenschemaDefinedInQuery=falseapache-commons-lang3StringUtilsdependency from this classAlterMaterializedTableChangeOperation: newvalidateChanges()method called fromexecute()rejects:ModifyColumnPosition) when the change set includesModifyDefinitionQueryModifyPhysicalColumnType) when the change set includesModifyDefinitionQueryDropColumn) unconditionallyAlso gains
computeNewTable()(protected hook),getOldTable(), andsetOldTable()(invalidates derived caches)MaterializedTableChangeHandler: removeisQueryChange,droppedPersistedCnt,validationErrors,checkForChangedPositionByQuery, and allpositionChangeErrorhelpers;dropColumnis now unconditional; unknown changes throw immediatelySqlAlterMaterializedTableDropSchemaConverter: remove the per-column persisted-column-drop guard (now handled byvalidateChanges)FullAlterMaterializedTableOperation: overridecomputeNewTable()with anewTableBuilderlambda supplied bySqlCreateOrAlterMaterializedTableConverter, so the caller controls the new-table construction without shadowing the cachednewTablefield on the parentSqlCreateOrAlterMaterializedTableConverter: extractbuildNewTable()that builds the new table definition with non-persisted columns absent from the explicit DDL dropped (declarative semantics); unfoldbuildTableChangesfrom a returned lambda into a direct method; addgetMergedLogicalRefreshMode,getMergedComment,getMergedFreshnesstoMergeContextVerifying this change
This change added tests and can be verified as follows:
AlterMaterializedTableChangeOperationValidationTest: rejects position changes, type changes, and persisted-column drops viavalidateChanges()AlterMaterializedTableAsQueryOperationValidationTest: end-to-end validation ofCREATE OR ALTERandALTER ... AS SELECTthroughexecute()MaterializedTableChangeHandlerTest: handler applies changes without validation side effectsValidateAndExtractColumnChangesTest: parametrized suite covering identical schemas, comment add/remove, column appended (with/withoutschemaDefinedInQuery), reordered persisted columns (no-op), type change, drop, rename, computed add/drop/modify, metadata add/dropSqlMaterializedTableNodeToOperationConverterTest: updated expected error messages and schema assertionsDoes this pull request potentially affect one of the following parts:
@Public(Evolving): noDocumentation
Was generative AI tooling used to co-author this PR?
Generated-by: Claude Code (claude-sonnet-4-6)