Skip to content

feat(sidebar): rename a table, a database and a schema from the object tree - #2559

Merged
datlechin merged 8 commits into
mainfrom
feat/rename-table-and-database
Aug 27, 2026
Merged

feat(sidebar): rename a table, a database and a schema from the object tree#2559
datlechin merged 8 commits into
mainfrom
feat/rename-table-and-database

Conversation

@datlechin

@datlechin datlechin commented Aug 27, 2026

Copy link
Copy Markdown
Member

Fixes #2482.

Follows #2556, now merged, which this needs: the rename reconciles open tabs against the same object identity that PR gives the staged table operations, and without it the rename would inherit the bare-name matching in a new place.

What this adds

Right-click a table and choose Rename. The row's label turns into a field: Return commits, Escape leaves it alone, clicking away commits the way Finder does. Container rows get Rename Database or Rename Schema in the engine's own vocabulary, so it reads Rename Keyspace on Cassandra and Rename Dataset on BigQuery.

Fifteen engines can rename a table, four can rename a database. The full matrix is in docs/features/table-operations.mdx.

Two departures from the issue

Not staged. The issue asks for it queued "like a drop or a truncate", covered by Preview SQL and Save Changes. It runs immediately instead, the way dropping a database already does.

Drop and truncate are queued because they are destructive and batchable: you pick several tables and confirm once. A rename is neither. And the row's label is the thing the user edits, so a queued rename would leave the tree showing a name the server does not have, with every later command on that row naming an object that does not exist.

No slow double-click. The issue asks for Finder's click-pause-click on the label. The tree cannot offer it: a single click already opens a preview tab and DatabaseTreeDoubleClickResolver already maps a double-click to "keep this one", so click-pause-click is two open gestures with a pause in the middle. Return is spent too, on performPrimaryAction. Apple documents neither: the HIG's outline-view guidance is single-click-to-edit, which is unavailable here for the same reason, and NSEvent.doubleClickInterval is declared once in AppKit and consumed by no API. The menu item is the whole trigger.

Where an engine cannot rename, the item is absent rather than dimmed. The issue asks for dimmed-with-a-reason, but DatabaseTreeMenuSpec already states and applies the opposite convention for Drop one function away, and one menu with two rules for the same situation is worse than either rule.

Shape

PluginKit gains three DriverPlugin capability statics and three PluginDatabaseDriver requirements, all with defaults. verify.sh abi main reports 33 additions and zero removals, so this is additive: no currentPluginKitVersion bump and no plugin re-release.

Renaming runs rather than generating a statement, matching dropDatabase rather than dropObjectStatement, because for several engines it is not a statement: MongoDB renames a collection through an admin command against admin, SQL Server calls sp_rename with string literals and a one-part new name. Each driver owns its own quoting and its own rule for the new name, which differ more than they look: PostgreSQL and Oracle reject a qualified new name, Snowflake accepts one and treats it as a move, SQLite refuses a view outright.

ObjectRenameEligibility is the pure gate, mirroring ContainerDropEligibility. A container is never renamed while the connection is on it, the same rule Drop applies, because PostgreSQL refuses outright and the engines that allow it leave the session on a name that has gone.

Writing the docs table caught a gap in the first pass: Redshift and CockroachDB carried the rename capability flags from the curated snapshot, but their drivers are siblings of PostgreSQLPluginDriver rather than subclasses, so the flags had nothing behind them and a rename would have thrown "this database cannot be renamed". The implementation now sits on the shared LibPQBackedDriver protocol, which PostgreSQL, Redshift, CockroachDB and PGlite all conform to. Every capability flag in the tree was then checked against an implementation, and every implementation against a flag.

The inline editor moves out of FavoritesOutlineCellView into RenamableSidebarCellView, which both sidebar lists now share; FavoritesOutlineCellView stays as a thin subclass supplying its own glyph and accessibility identifier.

What follows a rename

The object survives, so the state built around it survives too. Open tabs on that table keep their rows, filters, sort and column widths and rewrite their browse query; the window's change manager retargets, so a save started afterwards does not write to the old name; a favourite stays a favourite instead of syncing a table that no longer exists to every device; the Recent entry keeps its place rather than jumping to the top. A queued drop or truncate on the same table is cancelled, because the confirmation the user gave named the object they were looking at.

Verified

  • verify.sh build: PASS
  • verify.sh test over 13 suites: 120 executed, 120 passed
  • Every touched registry plugin built through its own scheme: MSSQL, MongoDB, DuckDB, BigQuery, Snowflake, Trino, Teradata, Dameng, Cloudflare D1, LibSQL and PostgreSQL, all PASS. The bundled ones ride the app build.
  • verify.sh abi main: additive, 33 additions and no removals
  • verify.sh lint TablePro Plugins: 0 violations
  • verify.sh docs: PASS

verify.sh plugins cannot run on this machine: the AllPlugins scheme fails in the pinned oracle-nio fork's @TaskLocal macro expansion, on main as well as here. CI compiles it. Oracle is therefore the one driver whose rename is unbuilt locally; its implementation is four lines of the same shape as Dameng's, which does build.

Every cell of the docs capability table was re-derived from the source after the code was final, per docs/STYLE.md section 9: the curated snapshot for the variant type ids that registerVariant resolves, the plugin static for the primary ids that buildMetadataSnapshot resolves, and the driver implementation behind each.

The two screenshots are placeholders at the corpus's 1560x960, so the page renders and the markup is correct. They need capturing before this ships.

No UI automation. The flow needs a live writable database to rename anything in, and the assertion worth making is that the label changed on the server rather than in the field. The decisions the flow rests on are unit-tested instead: which rows offer the item, what a typed name means, and what the menu emits per engine and under safe mode.

@mintlify

mintlify Bot commented Aug 27, 2026

Copy link
Copy Markdown

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

Project Status Preview Updated (UTC)
TablePro 🟢 Ready View Preview Aug 27, 2026, 9:18 AM

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

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

…-database

# Conflicts:
#	CHANGELOG.md
#	TablePro/Core/Database/TableOperationSQLBuilder.swift
#	TablePro/Views/Sidebar/Menu/SidebarMenuCommand.swift
#	TableProTests/Views/Sidebar/DatabaseTreeMenuSpecTests.swift
…-database

# Conflicts:
#	TablePro/Core/Plugins/PluginMetadataRegistry.swift
@datlechin
datlechin merged commit a62ee4f into main Aug 27, 2026
4 checks passed
@datlechin
datlechin deleted the feat/rename-table-and-database branch August 27, 2026 11:26
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.

Rename a table and rename a database

1 participant