Skip to content

[FLINK-39957][table] Support EXPLAIN of CREATE [OR ALTER] MATERIALIZED TABLE#28510

Open
raminqaf wants to merge 5 commits into
apache:masterfrom
raminqaf:os-flink-explain-create-mt
Open

[FLINK-39957][table] Support EXPLAIN of CREATE [OR ALTER] MATERIALIZED TABLE#28510
raminqaf wants to merge 5 commits into
apache:masterfrom
raminqaf:os-flink-explain-create-mt

Conversation

@raminqaf

Copy link
Copy Markdown
Contributor

What is the purpose of the change

EXPLAIN previously rejected materialized table DDL, so users had no way to inspect the plan that populates a materialized table without actually running it. This change adds EXPLAIN support for CREATE MATERIALIZED TABLE ... AS, CREATE OR ALTER MATERIALIZED TABLE ... AS (both the alter-on-existing and the in-place
table-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.

EXPLAIN stays 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 EXPLAIN time 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 connector
options. Resolving managed options at plan time without persisting is left as a follow-up.

Brief change log

  • Parser: allow CREATE/ALTER MATERIALIZED TABLE statements after EXPLAIN, and reject a non-AS ALTER under EXPLAIN with a clear message.
  • Make the materialized table create/alter/convert operations translatable as ModifyOperation, carrying the validated AS query as the sink input; ModifyOperationVisitor gains the corresponding visit methods.
  • Planner: convert the inner materialized table statement when explaining, and translate these operations into the sink RelNode that writes into the resulting table (reusing the existing table's resolved options for alter/convert).
  • Gateway: guard operation dispatch so directly-executed materialized table statements still route to MaterializedTableManager rather than the generic ModifyOperation translation path (the new ModifyOperation role only enables EXPLAIN, it must not change execution).

Verifying this change

This change added tests and can be verified as follows:

  • Parser tests for EXPLAIN of CREATE/CREATE OR ALTER/ALTER MATERIALIZED TABLE, including the rejection of a non-AS ALTER.
  • Planner plan tests (TableSinkTest) asserting the AST / optimized physical / optimized execution plans for the create and alter variants.
  • Gateway integration tests asserting the full EXPLAIN plan end-to-end (against golden resources) for ALTER ... AS, CREATE OR ALTER on an existing materialized table, and the table-to-materialized-table conversion, plus assertions that EXPLAIN leaves the catalog object unchanged.
  • Existing materialized table create/alter/convert ITs continue to pass, confirming direct execution dispatch is unchanged.

Does this pull request potentially affect one of the following parts:

  • Dependencies (does it add or upgrade a dependency): no
  • The public API, i.e., is any changed class annotated with @Public(Evolving): no
  • The serializers: no
  • The runtime per-record code paths (performance sensitive): no
  • Anything that affects deployment or recovery: JobManager (and its components), Checkpointing, Kubernetes/Yarn, ZooKeeper: no
  • The S3 file system connector: no

Documentation

  • Does this pull request introduce a new feature? yes
  • If yes, how is the feature documented? not documented (a follow-up should note EXPLAIN support on the materialized table / EXPLAIN statement docs)

AI-tooling disclosure

Generated cleanups by Claude Opus 4.8

@flinkbot

flinkbot commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

CI report:

Bot commands The @flinkbot bot supports the following commands:
  • @flinkbot run azure re-run the last Azure build

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)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason MaterializedTableOperation is not a ModifyOperation

however after that we call callModifyOperations ?

assertThat(
service.getTable(sessionHandle, getObjectIdentifier("users_shops"))
.getTableKind())
.isSameAs(CatalogBaseTable.TableKind.TABLE);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use static import if it requires more than 2 names

* golden resource. The per-test catalog name is normalized to {@code $CATALOG} before
* comparison.
*/
static void verifyExplainPlan(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to create another plan verifier if there is already existing framework for this?
See TableTestBase

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(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants