Skip to content

adapter: Further preparations for handling query plans in catalog implications#35837

Merged
ggevay merged 2 commits intoMaterializeInc:mainfrom
ggevay:implications-optimizer
May 5, 2026
Merged

adapter: Further preparations for handling query plans in catalog implications#35837
ggevay merged 2 commits intoMaterializeInc:mainfrom
ggevay:implications-optimizer

Conversation

@ggevay
Copy link
Copy Markdown
Contributor

@ggevay ggevay commented Apr 2, 2026

This is further preparation for handling those DDL commands in the catalog implications that need query plans. The 2 commits move things from the catalog transaction's side effect closure to before the catalog transaction. See more details in the commit messages.

The important thing is that this unlocks a later change that reads plans back from the cache in parse_item. (Draft PR: #36146)

Nightly: https://buildkite.com/materialize/nightly/builds/16131 (slightly stale)

@ggevay ggevay added the A-ADAPTER Topics related to the ADAPTER layer label Apr 2, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 2, 2026

Thanks for opening this PR! Here are a few tips to help make the review process smooth for everyone.

PR title guidelines

  • Use imperative mood: "Fix X" not "Fixed X" or "Fixes X"
  • Be specific: "Fix panic in catalog sync when controller restarts" not "Fix bug" or "Update catalog code"
  • Prefix with area if helpful: compute: , storage: , adapter: , sql:

Pre-merge checklist

  • The PR title is descriptive and will make sense in the git log.
  • This PR has adequate test coverage / QA involvement has been duly considered. (trigger-ci for additional test/nightly runs)
  • If this PR includes major user-facing behavior changes, I have pinged the relevant PM to schedule a changelog post.
  • This PR has an associated up-to-date design doc, is a design doc (template), or is sufficiently small to not require a design.
  • If this PR evolves an existing $T ⇔ Proto$T mapping (possibly in a backwards-incompatible way), then it is tagged with a T-proto label.
  • If this PR will require changes to cloud orchestration or tests, there is a companion cloud PR to account for those changes that is tagged with the release-blocker label (example).

@ggevay ggevay force-pushed the implications-optimizer branch from 1580288 to 1057460 Compare April 9, 2026 12:17
ggevay added a commit that referenced this pull request Apr 17, 2026
This is preparation for moving those catalog operations into the catalog
implications framework that involve query plans, such as `CREATE
MATERIALIZED VIEW`.

This PR solves a long-standing weirdness in our catalog: We used to have
query plans and other metainfo in a separate part of the catalog
(`CatalogPlans`), instead of inside the catalog items. This happened
only due to historical reasons. This PR fixes this.

I recommend reviewing commit by commit.

The 1st is just some renaming to avoid confusion between locally
optimized plans (with just `optimize_mir_local` without view inlining)
and fully (globally) optimized plans (that is, after view inlining, with
`optimize_dataflow`).

The 2nd commit is the main thing, see commit msg for details.

(Note that even after this PR, we are still adding the plans in the side
effect closure of the catalog transactions that adds the catalog items,
e.g., in `create_materialized_view_finish`.
#35837 will be a
follow-up PR, which will instead add the plans to the `catalog::Op`s
that comprise the catalog transactions.)

Nightly: https://buildkite.com/materialize/nightly/builds/15973, but
there is a staggering amount of unrelated redness, so it's hard to read.

---------

Co-authored-by: Junie <junie@jetbrains.com>
@ggevay ggevay force-pushed the implications-optimizer branch 2 times, most recently from cff16bc to f45a28c Compare April 19, 2026 12:29
@ggevay ggevay force-pushed the implications-optimizer branch 4 times, most recently from 96637fc to 5326805 Compare April 20, 2026 14:08
@ggevay ggevay marked this pull request as ready for review April 20, 2026 15:13
@ggevay ggevay requested a review from a team as a code owner April 20, 2026 15:13
@ggevay ggevay requested review from SangJunBak, aljoscha and mtabebe and removed request for SangJunBak April 20, 2026 15:13
Copy link
Copy Markdown
Contributor

@mtabebe mtabebe left a comment

Choose a reason for hiding this comment

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

Great test coverage. And I think that I have reviewed some of these commits before. So I mainly focused on the last one. It looks good. Just one minor question

)
};

// Populate the durable expression cache before the catalog
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.

What happens if the transaction fails? My assumption is that it ok to cache the expression of failed transactions... just confirming

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.

Similarly, how do we handle notices if the transaction doesn't succeed? Will this state just remain around forever?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good questions!

Expression cache on failed transaction: Yes, harmless. The cache entry is keyed by (build_version, GlobalId, expr_type). If the transaction fails, that GlobalId never lands in the catalog, so the entry is never looked up — get_global_expressions (in the follow-up PR) only queries GlobalIds from Op::CreateItem ops that are actually being committed. The orphaned entry sits inert in the persist shard until the next version bump cleans it up via remove_prior_versions.

Notices on failed transaction: This is actually the exact bug this PR fixes! Pre-fix, emit_optimizer_notices ran before the catalog transaction, so the user saw spurious notices (e.g. "identical index already exists") even when IF NOT EXISTS hit a name collision and the item wasn't created. Post-fix:

  • Raw notices to the user (emit_raw_optimizer_notices_to_user) are emitted only in the Ok(_) arm after the transaction succeeds.
  • Rendered notices persisted to mz_optimizer_notices (via persist_dataflow_metainfo) only happen inside the side-effect closure, which only runs on success.
  • Rendered notices in the expression cache are only consumed by parse_item during apply_updates for committed transactions, so also inert on failure.

The new notice.pt test at the bottom of the PR pins this invariant for both CREATE INDEX IF NOT EXISTS and CREATE MATERIALIZED VIEW IF NOT EXISTS.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah lol, Claude just went ahead and posted this when I asked it to draft a reply :D

Copy link
Copy Markdown
Contributor Author

@ggevay ggevay May 5, 2026

Choose a reason for hiding this comment

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

But yeah, its answer is mostly right: The important thing is that this is only a small amount of orphaned data, and it gets cleaned up on the next version upgrade, because the expression cache is scoped to a version.

Moves `render_notices` out of the side-effect closure of
`catalog_transact_with_side_effects` in `create_index_finish` and
`create_materialized_view_finish`. Renders notices pre-transaction
using an `ExprHumanizerExt` wrapping `for_system_session()` that
knows about the to-be-created item's `global_id` and full name,
matching the pattern already used by the `_explain` paths.

Splits the old `process_dataflow_metainfo` into two narrower
helpers:
- `emit_raw_optimizer_notices_to_user`: forwards raw notices to
  the user's session (still session-aware humanizer).
- `persist_dataflow_metainfo`: takes already-rendered notices,
  packs `mz_optimizer_notices` builtin-table updates, and stores
  the metainfo on the catalog object.

Extracts the humanizer-agnostic rendering core into
`CatalogState::render_notices_core(&dyn ExprHumanizer,
EpochMillis, ...)`. `Catalog::render_notices` remains as a thin
adapter for existing callers (bootstrap path, CT).

Unblocks a follow-up change that moves `cache_expressions` before
the transaction so that the durable expression cache ends up with
rendered notices.

Co-authored-by: Junie <junie@jetbrains.com>
@ggevay ggevay force-pushed the implications-optimizer branch from 5326805 to 7127b5f Compare May 5, 2026 12:28
`Catalog::cache_expressions` used to:
- read plans + metainfo from in-memory catalog state (after they
  had been installed by `set_optimized_plan` /
  `set_physical_plan` / `set_dataflow_metainfo`), and
- drop the future returned by `update_expression_cache`
  (`let _fut = ...`), so the cache write raced with the catalog
  transaction commit.

Both properties block the long-term goal of having the durable
expression cache be a valid source of truth for plans and
rendered notices across envd processes: the write needs to be
observed before the item becomes visible, and the function must
be callable before the catalog state is mutated.

This commit:
- Changes `Catalog::cache_expressions` to take the plans and
  metainfo directly as parameters, and to return the future
  from `update_expression_cache` rather than dropping it.
- Moves the call ahead of `catalog_transact_with_side_effects`
  in `create_index_finish` and `create_materialized_view_finish`
  and `.await`s it there.

Together with the preceding commit (rendered notices
pre-transaction), the durable expression cache now contains
rendered notices and is committed before the catalog transaction
commits, unblocking a later change that reads plans back from
the cache in `parse_item`.
@ggevay ggevay force-pushed the implications-optimizer branch from 7127b5f to f3c147f Compare May 5, 2026 12:46
@ggevay ggevay merged commit 7f632d2 into MaterializeInc:main May 5, 2026
123 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-ADAPTER Topics related to the ADAPTER layer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants