Skip to content

feat(db): PostgreSQL 外部表与物化视图纳入树、动作与转储 - #266

Merged
feigeCode merged 1 commit into
devfrom
feat/pg-foreign-table-matview
Sep 21, 2026
Merged

feigeCode merged 1 commit into
devfrom
feat/pg-foreign-table-matview

Conversation

@feigeCode

Copy link
Copy Markdown
Owner

Description

PostgreSQL connections only ever listed base tables: the listing SQL was hardcoded to c.relkind = 'r', so foreign tables ('f') and partitioned tables ('p') were invisible, and materialized views had no entry point at all (plain views were resolved through information_schema.views, which excludes matviews). A user who had already created foreign tables with Navicat could not see them in Navop.

This PR aligns the PostgreSQL object tree with Navicat and makes the actions correct, not just visible:

  • Listinglist_tables / list_tables_view now accept 'r','p','f' and map relkind to an object type ('f'ForeignTable, 'p'/'r'Table). The object list "type" column shows Table / Partitioned Table / Foreign Table. New list_materialized_views reads pg_class (relkind = 'm') plus pg_get_viewdef, so materialized views no longer mix into plain views.
  • Tree — new DbNodeType::{ForeignTable, MaterializedViewsFolder, MaterializedView}. Foreign, base and partitioned tables share one "Tables" folder (Navicat behavior); materialized views get their own folder, gated by a new supports_materialized_views capability flag (defaults to false, so MySQL and other drivers are unaffected).
  • Actions — foreign tables and materialized views get their menu scoped per node type (Open / Rename / Truncate / Drop / Dump / Import / Export). Delete and rename dispatch by type to drop_foreign_table / rename_foreign_table / drop_materialized_view, so a plain DROP TABLE can never be sent to a foreign table. Actions without an implementation (design foreign table, copy table, foreign-table structure dump) are simply not registered, so no dead menu entries appear.
  • Compare & dump — new TableObjectType::ForeignTable; is_ddl_comparable() keeps only plain tables, so foreign tables are automatically excluded from schema compare, data compare, ER diagram and whole-database DDL dump (data dump still works). resolve_sql_dump_target learns the new types so "Dump SQL File" no longer fails silently.
  • Schema qualificationrename_foreign_table / drop_materialized_view now take a schema and emit schema-qualified names. The execution session never switches search_path, so on non-public schemas the previous DDL would have hit the wrong relation or errored out.

How to Test

# Unit / widget tests
cargo test -p db --lib          # 1305 passed
cargo test -p db_view --lib     # 703 passed, 1 ignored
cargo check --workspace --all-targets

# Real PostgreSQL integration test (skips unless the password env var is set)
ONETCLI_TEST_POSTGRES_PASSWORD=<password> cargo test -p db --test real_postgres   # 5 passed

The new crates/db/tests/real_databases/postgres/foreign_matview.rs creates a non-public schema with a real postgres_fdw foreign table (own foreign server + user mapping), a partitioned table and a materialized view, then asserts listing types, object-list types and tree placement, and actually executes rename/drop on the foreign table and drop on the materialized view. It also verifies list_views does not leak materialized views. The test cleans up after itself — no schema, foreign server or extension is left behind in the target database.

Manual smoke test: connect to a PostgreSQL database; the Tables folder now shows base, partitioned and foreign tables together with correct type labels, and a Materialized Views folder lists matviews with working Open Data / Dump / Delete.

Checklist

  • I have read the CONTRIBUTING document and followed the guidelines.
  • Reviewed the changes in this PR and confirmed AI generated code (If any) is accurate.
  • Passed cargo run for story tests related to the changes. — not run: the story gallery is an interactive GUI; the touched views are covered by cargo test -p db_view instead, and the right-click menu click path has no automated regression yet.
  • Tested macOS, Windows and Linux platforms performance (if the change is platform-specific) — not applicable, no platform-specific code.

PG 连接的表目录写死 `c.relkind = 'r'`,外部表('f')和分区表('p')根本列不出来,
物化视图也找不到入口(视图走 `information_schema.views`,它不含物化视图)——与
Navicat 的行为不一致,用户已经建好的外部表在 Navop 里等于不存在。

- 列表:`list_tables` / `list_tables_view` 放开 relkind 到 `'r','p','f'`,按 relkind
  映射对象类型('f' → ForeignTable,'p'/'r' → Table),对象列表「类型」列分别显示
  Table / Partitioned Table / Foreign Table;新增 `list_materialized_views`(走
  `pg_class` relkind='m' + `pg_get_viewdef`),物化视图从普通视图里彻底分离。
- 树:新增 `DbNodeType::{ForeignTable, MaterializedViewsFolder, MaterializedView}`,
  外部表与普通表/分区表同处「表」目录(对齐 Navicat),物化视图单独一个目录;目录由
  `supports_materialized_views` 能力位控制,MySQL 等其它驱动不受影响。
- 动作:外部表与物化视图按 node_type 各自 scope 出菜单(Open / Rename / Truncate /
  Drop / Dump / Import / Export 等),删除与重命名按类型分派到 `drop_foreign_table`
  / `rename_foreign_table` / `drop_materialized_view`——不能把 `DROP TABLE` 打到外部表
  上。设计表 / 复制表 / 结构转储等尚无实现的动作不注册,因此不会出现点了没反应的项。
- 结构比较与结构转储:新增 `TableObjectType::ForeignTable`,`is_ddl_comparable()` 只让
  普通表参与,外部表自动从结构比较、数据比较、ER 图、整库 DDL 转储中排除(数据转储
  仍可用);`resolve_sql_dump_target` 补上新类型的映射,避免 Dump 静默报错。
- schema 限定:`rename_foreign_table` / `drop_materialized_view` 接受 schema 并生成
  schema 限定名——执行会话不会切 search_path,非 public schema 下的 DDL 原先会打错
  对象(或直接报错)。

验证:

- `cargo test -p db --lib` 1305 passed / 0 failed;`cargo test -p db_view --lib`
  703 passed / 0 failed / 1 ignored;`cargo check --workspace --all-targets` 无
  error/warning;对新增行做 clippy 比对,无新增告警。
- 新增真实库集成测试 `crates/db/tests/real_databases/postgres/foreign_matview.rs`
  (设置 `ONETCLI_TEST_POSTGRES_PASSWORD` 后才运行):在非 public schema 下真建外部表
  (postgres_fdw)、分区表与物化视图,断言列表类型、对象面板类型与树的归属,并真实
  执行 rename / drop 外部表和 drop 物化视图,最后校验 `list_views` 不混入物化视图。
  `cargo test -p db --test real_postgres` 5 passed;测试自带清理,不在库里留 schema、
  外部服务器或扩展。
- 未验证:GUI 端到端(右键菜单实际点击路径)没有真机回归,只覆盖到事件与 SQL 生成层。
@feigeCode
feigeCode merged commit e847fbb into dev Sep 21, 2026
8 checks passed
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.

1 participant