Skip to content

fix(coordinator): drop materialized views and foreign tables with the correct DROP statement#1801

Merged
datlechin merged 1 commit into
mainfrom
fix/drop-materialized-view-1800
Jul 2, 2026
Merged

fix(coordinator): drop materialized views and foreign tables with the correct DROP statement#1801
datlechin merged 1 commit into
mainfrom
fix/drop-materialized-view-1800

Conversation

@datlechin

Copy link
Copy Markdown
Member

Fixes #1800.

Problem

Dropping a materialized view from the sidebar sent DROP TABLE <name>, which the server rejects (PostgreSQL: "name" is not a table). Foreign tables hit the same bug.

Root cause

The metadata pipeline, sidebar sections, and context-menu labels all carry the correct object kind (TableInfo.TableType), but the drop action stores only names in pendingDeletes: Set<String>. At SQL-generation time the kind was re-derived as isView: Bool from a closure that only recognized .view, so materialized views and foreign tables fell into the DROP TABLE branch.

A second bug sat one layer up: the ClickHouse driver classified engines with engine?.contains("View"), which matches "MaterializedView" as a substring, so ClickHouse materialized views were misfiled as plain views at the metadata level.

Fix

  • TableOperationSQLBuilder now takes tableInfoProvider: () -> [String: TableInfo] instead of viewNamesProvider: () -> Set<String> and maps the kind through an exhaustive switch: VIEW, MATERIALIZED VIEW, FOREIGN TABLE, and TABLE for tables, system tables, and lookup misses (miss logs an OSLog warning). Drop and truncate statements are now schema-qualified from the same lookup.
  • This fixes every driver that reports materialized views (PostgreSQL, BigQuery, Cassandra) with zero PluginKit ABI change: dropObjectStatement(objectType: String) already accepts a free-form keyword.
  • ClickHouse: exact-match engine classifier (MaterializedView -> MATERIALIZED VIEW; View/LiveView/WindowView -> VIEW), a dropObjectStatement override that emits DROP VIEW for materialized views (ClickHouse has no DROP MATERIALIZED VIEW statement), and the .materializedViews capability so they get their own sidebar section and the "Drop Materialized View" menu label.

Tests

  • New TableOperationSQLBuilderTests: one case per object kind, cascade, schema qualification, and the lookup-miss fallback. The old suite ran with no session registered, so isView: true was never exercised; this is the gap that let the bug ship.
  • New ClickHouseTableOperationsTests for the engine classifier and drop statement (compiled into TableProTests via a pbxproj membership exception, same pattern as MySQLQueryTimeoutStatement.swift).
  • PluginDriverAdapterTableOpsTests gains MATERIALIZED VIEW and FOREIGN TABLE fallback cases.
  • No UI automation: dropping a materialized view needs a live server with matview support, which the deterministic UI fixture set (SQLite) does not have.

Notes

  • The pbxproj diff includes Xcode's own normalization of the DuckDB and Elasticsearch product references alongside the new test-membership exception.
  • Known pre-existing limitation, not worsened here: pendingDeletes is keyed by bare name, so two same-named objects in different schemas cannot be pending-dropped at once. Worth a separate issue.

@mintlify

mintlify Bot commented Jul 2, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
TablePro 🟢 Ready View Preview Jul 2, 2026, 12:44 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@datlechin datlechin merged commit 491aed6 into main Jul 2, 2026
3 checks passed
@datlechin datlechin deleted the fix/drop-materialized-view-1800 branch July 2, 2026 12:51

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 55f7f7f95d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return Set(session.tables.filter { $0.type == .view }.map(\.name))
tableInfoProvider: {
guard let session = DatabaseManager.shared.session(for: self.connectionId) else { return [:] }
return Dictionary(session.tables.map { ($0.name, $0) }, uniquingKeysWith: { first, _ in first })

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve schema when resolving pending drops

When the sidebar/database tree has objects with the same name in different schemas, the pending operation still carries only the bare table name, but this new lookup collapses session.tables by name and keeps an arbitrary/first TableInfo. Because the builder now uses that TableInfo.schema to qualify DROP/TRUNCATE, selecting sales.orders can preview or execute against public.orders if that entry is first or the current schema cache is stale after a schema switch. Please carry the selected schema (or the full TableInfo) through the pending operation instead of resolving destructive SQL by bare name.

Useful? React with 👍 / 👎.

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.

Drop MATERIALIZED view error

1 participant