Hi Xuyang, Hi Gustavo,

Thank you for reviewing this FLIP, and the positive feedback!

If there are no objections, I would start the VOTE for it tomorrow.

Best,
Timo

On Wed, Oct 21, 2026 at 8:56 AM Gustavo de Morais <[email protected]>
wrote:

> Hi Timo,
>
> Materialized Tables are a key part of an easier interface for creating
> Flink jobs and having it exposed in TableAPI makes a lot of sense. I like
> the detailed examples and the FLIP looks good to me.
>
> Thanks for working on it +1.
>
> Kind regards,
> Gustavo
>
> On Wed, 21 Oct 2026 at 07:39, Xuyang <[email protected]> wrote:
>
> > Hi Timo,
> > That makes sense to me. +1
> >
> >
> >
> >
> >
> > --
> >
> >     Best!
> >     Xuyang
> >
> >
> >
> > At 2026-10-19 17:12:58, "Timo Theusner" <[email protected]> wrote:
> > >Hi Xuyang,
> > >
> > >Thanks, good to hear resume() as the fallback works for you.
> > >Regarding the flag, I'd rather not like to add one at this point. RESUME
> > on
> > >an ACTIVATED table is already a recovery-only call. While the job runs
> it
> > >is rejected, and for a job that has ended it already starts a new one,
> > >without deleting the existing table. A flag would add new syntax to SQL
> > and
> > >the Table API for a rare case. I would say resume() should log a warning
> > >that names the cluster it checked, and the docs should state that a
> table
> > >should only be resumed once its old refresh job can no longer write. Let
> > me
> > >know if that makes sense to you or if I overlooked a specific case here.
> > >
> > >Best,
> > >Timo
> > >
> > >On Fri, Oct 16, 2026 at 5:19 AM Xuyang <[email protected]> wrote:
> > >
> > >> Hi, Timo. I don’t have any further concerns about the other points.
> > >> Regarding point 4, I think using resume() as a fallback to recover an
> > >> ACTIVATED table whose refresh job has disappeared is reasonable.
> > Perhaps we
> > >> could provide an optional parameter similar to IGNORE NOT EXISTS or
> > FORCE
> > >> (the exact name can be discussed and disabled by default), allowing
> > users
> > >> to restart the job without deleting the existing table data. What do
> you
> > >> think?
> > >>
> > >>
> > >>
> > >> --
> > >>
> > >>     Best!
> > >>     Xuyang
> > >>
> > >>
> > >>
> > >> At 2026-10-15 23:27:38, "Timo Theusner" <[email protected]>
> > wrote:
> > >> >Hi Xuyang,
> > >> >
> > >> >Thank you for your feedback. Regarding your questions and comments:
> > >> >
> > >> >1. For a materialized table declared from the Table API both would
> > return
> > >> >the same SQL, generated by QueryOperation#asSerializableString(). But
> > for
> > >> a
> > >> >materialized table declared in SQL, they would return two different
> > >> >strings. When inspecting a materialized table with
> > >> >TableEnvironment#fromMaterializedTable(...), which was created via
> SQL,
> > >> >getOriginalQuery() will return the user-written query, while
> > >> >getExpandedQuery() returns the validated query with every identifier
> > fully
> > >> >qualified. Regarding queries that have no SQL serialization yet, like
> > >> >session windows, would be rejected at materializeInto(...) with a
> > >> >ValidationException before anything is written to the catalog. These
> > query
> > >> >limitations will be explicitly documented.
> > >> >2. I would propose to apply changes in call order, each to the result
> > of
> > >> >the earlier ones, as the SQL sequence in the user journey shows. So
> > >> >option(k, v).resetOption(k) resets k. I think this is the simplest
> rule
> > >> >because it is what already happens when using SQL, where a user also
> > runs
> > >> >alter queries in order. Also rejecting conflicts would need a rule
> for
> > >> >every pair of calls and would make the Table API stricter than SQL.
> > I'll
> > >> >add this to the execute() Javadoc.
> > >> >3. I agree with you, it can be done as an improvement in the future.
> > >> >4. In that case can't resume() be the recovering option here? When we
> > >> >reject a redeploy due to the mentioned inconsistency we can issue a
> > proper
> > >> >error message with guidance. Users should confirm if their job is
> > stopped
> > >> >and can no longer write, once they are sure they can run resume() to
> > start
> > >> >a new refresh job without state and keep the table and its data. What
> > do
> > >> >you think about this?
> > >> >
> > >> >I'll update the FLIP shortly with these information.
> > >> >
> > >> >Best,
> > >> >Timo
> > >> >
> > >> >
> > >> >On Mon, Oct 12, 2026 at 11:31 AM Xuyang <[email protected]> wrote:
> > >> >
> > >> >> Hi, Timo.
> > >> >> Thanks for the proposal. Having Table API support for materialized
> > >> tables
> > >> >> would be useful, especially for defining and managing pipelines
> > >> directly in
> > >> >> Java. I have a few questions about the new API, along with some
> > >> thoughts on
> > >> >> the redeploy and recovery behavior:
> > >> >> 1. For materialized tables defined through the Table API, what
> would
> > >> >> getOriginalQuery() and getExpandedQuery() return? Since there is no
> > >> >> user-written SQL, would they return generated SQL? If the
> > implementation
> > >> >> uses QueryOperation#asSerializableString(), existing serialization
> > does
> > >> not
> > >> >> support queries such as session windows. Would these limitations be
> > >> >> explicitly documented?
> > >> >> 2. MaterializedTableEvolution combines multiple changes into a
> single
> > >> >> ALTER. How are ordering and conflicts handled? For example, would
> > >> option(k,
> > >> >> v).resetOption(k) be applied in invocation order, with the last
> > >> operation
> > >> >> taking precedence, or be rejected as a conflict?
> > >> >> 3. Regarding your point about restarting jobs on redeploy, I think
> > the
> > >> >> current behavior of always restarting could be improved. However,
> > some
> > >> >> changes may be difficult to detect, such as changes to UDF
> > >> implementations,
> > >> >> upstream table configurations, or the underlying data. In any case,
> > this
> > >> >> could be addressed as a separate, small follow-up improvement.
> > >> >> 4. Regarding inconsistencies between the metadata in the MT catalog
> > and
> > >> >> the actual cluster state, I don’t think requiring users to
> recreate a
> > >> >> cluster with the same ID just to execute DROP is reasonable.
> Perhaps
> > we
> > >> >> could provide an explicit recovery option: once the old job is
> > >> confirmed to
> > >> >> be absent or stopped, users could redeploy the refresh job to the
> > target
> > >> >> cluster while preserving the existing table and its data. If the
> old
> > >> >> cluster is unreachable, users would first need to ensure that the
> old
> > >> job
> > >> >> can no longer write, to avoid two jobs writing to the same table
> > >> >> concurrently.
> > >> >> I look forward to hearing your thoughts.
> > >> >>
> > >> >>
> > >> >>
> > >> >> --
> > >> >>
> > >> >>     Best!
> > >> >>     Xuyang
> > >> >>
> > >> >>
> > >> >>
> > >> >> At 2026-10-09 23:40:44, "Timo Theusner" <[email protected]>
> > >> wrote:
> > >> >> >Hi everyone,
> > >> >> >
> > >> >> >I'd like to start a discussion on FLIP-616: Materialized Tables
> > support
> > >> >> for
> > >> >> >Table API [1].
> > >> >> >
> > >> >> >Materialized tables (FLIP-435 [2]) have become a convenient way to
> > >> define
> > >> >> >pipelines declaratively. So far, though, this only works via SQL
> > >> against
> > >> >> >the SQL Gateway. Table API users can list materialized tables, but
> > they
> > >> >> >cannot define or manage them, and running the DDL through
> > executeSql()
> > >> >> >only gets them halfway, since the table is registered but no
> refresh
> > >> job
> > >> >> is
> > >> >> >ever started.
> > >> >> >
> > >> >> >The FLIP closes this gap. A Table can be turned into a
> materialized
> > >> table
> > >> >> >via Table#materializeInto(...), optionally with a descriptor for
> > >> >> >freshness, refresh strategy, schema details or start mode. The
> > result
> > >> is a
> > >> >> >MaterializedTable handle that lets users change, inspect, and
> > control
> > >> it.
> > >> >> >To avoid two diverging implementations, the logic currently living
> > in
> > >> the
> > >> >> >SQL Gateway moves into the planner, so the gateway and the Table
> > >> >> >API behave the same. From a regular Table API program, continuous
> > >> >> refreshes
> > >> >> >work against a session cluster. Full refresh mode still
> > >> >> >needs the gateway for now, since it depends on a workflow
> scheduler.
> > >> As a
> > >> >> >side effect, executeSql() would then actually manage refresh jobs
> > >> >> >for materialized table statements outside the gateway.
> > >> >> >
> > >> >> >There are two points I'd especially like your input on:
> > >> >> >1. Should redeploying an unchanged definition restart the refresh
> > job?
> > >> >> >    Today, CREATE OR ALTER always stops the job and starts a new
> one
> > >> >> >without state, even if nothing changed. Since the list of changes
> is
> > >> >> already
> > >> >> >    computed, skipping the restart when it is empty would be a
> small
> > >> >> check.
> > >> >> >On the other hand, always restarting keeps the semantics simple
> for
> > now
> > >> >> >    and matches what SQL does today.
> > >> >> >2. How should users get out of "stuck" tables?
> > >> >> >    If the cluster no longer "knows" the refresh job of an
> ACTIVATED
> > >> >> table,
> > >> >> >a redeploy is rejected, even though it would start a fresh job
> > without
> > >> >> state
> > >> >> >    anyway. That leaves DROP as the only way out, and for catalogs
> > that
> > >> >> own
> > >> >> >the storage, DROP also deletes the data. If the cluster is not
> > >> reachable
> > >> >> >    at all, the only workaround is to start a cluster under the
> > >> recorded
> > >> >> >cluster ID so that DROP sees the job as gone. Is that acceptable,
> or
> > >> >> should
> > >> >> >a
> > >> >> >    redeploy be able to recover such tables?
> > >> >> >
> > >> >> >Looking forward to your thoughts and feedback!
> > >> >> >
> > >> >> >Best,
> > >> >> >Timo
> > >> >> >
> > >> >> >[1]
> > >> >> >
> > >> >>
> > >>
> >
> https://cwiki.apache.org/confluence/spaces/FLINK/pages/451979479/FLIP-616+Materialized+Tables+support+for+Table+API
> > >> >> >
> > >> >> >[2]
> > >> >> >
> > >> >>
> > >>
> >
> https://cwiki.apache.org/confluence/spaces/FLINK/pages/294816797/FLIP-435+Introduce+a+New+Materialized+Table+for+Simplifying+Data+Pipelines
> > >> >>
> > >>
> >
>

Reply via email to