[FLINK-39957][table] Support EXPLAIN of CREATE [OR ALTER] MATERIALIZED TABLE#28510
Open
raminqaf wants to merge 5 commits into
Open
[FLINK-39957][table] Support EXPLAIN of CREATE [OR ALTER] MATERIALIZED TABLE#28510raminqaf wants to merge 5 commits into
raminqaf wants to merge 5 commits into
Conversation
…LE in the SQL parser
…translatable as ModifyOperation
…R to a sink RelNode for EXPLAIN
… manager and add EXPLAIN ITs
…-table conversion
Collaborator
snuyanzin
reviewed
Jun 22, 2026
| throw new SqlExecutionException( | ||
| "No Statement Set to submit. 'END' statement should be used after 'BEGIN STATEMENT SET'."); | ||
| } else if (op instanceof ModifyOperation) { | ||
| } else if (op instanceof ModifyOperation && !(op instanceof MaterializedTableOperation)) { |
Contributor
There was a problem hiding this comment.
is there a reason MaterializedTableOperation is not a ModifyOperation
however after that we call callModifyOperations ?
snuyanzin
reviewed
Jun 22, 2026
| assertThat( | ||
| service.getTable(sessionHandle, getObjectIdentifier("users_shops")) | ||
| .getTableKind()) | ||
| .isSameAs(CatalogBaseTable.TableKind.TABLE); |
Contributor
There was a problem hiding this comment.
use static import if it requires more than 2 names
snuyanzin
reviewed
Jun 22, 2026
| * golden resource. The per-test catalog name is normalized to {@code $CATALOG} before | ||
| * comparison. | ||
| */ | ||
| static void verifyExplainPlan( |
Contributor
There was a problem hiding this comment.
why do we need to create another plan verifier if there is already existing framework for this?
See TableTestBase
snuyanzin
reviewed
Jun 22, 2026
Comment on lines
+119
to
+128
| public static PlannerQueryOperation validateAndConvertAsQuery( | ||
| SqlNode asQuery, ConvertContext context) { | ||
| final FlinkPlannerImpl flinkPlanner = context.getFlinkPlanner(); | ||
| final SqlNode validated = flinkPlanner.validate(asQuery); | ||
| final Operation operation = | ||
| SqlNodeToOperationConversion.convert( | ||
| flinkPlanner, context.getCatalogManager(), validated) | ||
| .orElseThrow( | ||
| () -> | ||
| new TableException( |
Contributor
There was a problem hiding this comment.
method has pretty generic name, then somewhere in the middle it throws
"Unsupported materialized table definition query: "
either make it generic or may be rename and move into. materializedTableUtils
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
EXPLAINpreviously rejected materialized table DDL, so users had no way to inspect the plan that populates a materialized table without actually running it. This change addsEXPLAINsupport forCREATE MATERIALIZED TABLE ... AS,CREATE OR ALTER MATERIALIZED TABLE ... AS(both the alter-on-existing and the in-placetable-to-materialized-table conversion path from FLINK-39847), and
ALTER MATERIALIZED TABLE ... AS. The produced plan is the sink that writes the definition query into the materialized table, mirroring how CTAS/RTAS are explained.EXPLAINstays side-effect-free: no table is created, altered, or converted, and no refresh job is submitted.Note on scope: building the sink for a brand-new managed materialized table at
EXPLAINtime is not covered, because a managed table's storage options (e.g.path) are only assigned by the catalog at creation time. The alter and conversion paths work because they reuse the existing table's already-resolved connectoroptions. Resolving managed options at plan time without persisting is left as a follow-up.
Brief change log
CREATE/ALTER MATERIALIZED TABLEstatements afterEXPLAIN, and reject a non-ASALTERunderEXPLAINwith a clear message.ModifyOperation, carrying the validatedASquery as the sink input;ModifyOperationVisitorgains the correspondingvisitmethods.RelNodethat writes into the resulting table (reusing the existing table's resolved options for alter/convert).MaterializedTableManagerrather than the genericModifyOperationtranslation path (the newModifyOperationrole only enablesEXPLAIN, it must not change execution).Verifying this change
This change added tests and can be verified as follows:
EXPLAINofCREATE/CREATE OR ALTER/ALTER MATERIALIZED TABLE, including the rejection of a non-ASALTER.TableSinkTest) asserting the AST / optimized physical / optimized execution plans for the create and alter variants.EXPLAINplan end-to-end (against golden resources) forALTER ... AS,CREATE OR ALTERon an existing materialized table, and the table-to-materialized-table conversion, plus assertions thatEXPLAINleaves the catalog object unchanged.Does this pull request potentially affect one of the following parts:
@Public(Evolving): noDocumentation
EXPLAINsupport on the materialized table /EXPLAINstatement docs)AI-tooling disclosure
Generated cleanups by Claude Opus 4.8