feat(structure): add Triggers tab to Show Structure for MySQL, PostgreSQL, and SQLite#1696
feat(structure): add Triggers tab to Show Structure for MySQL, PostgreSQL, and SQLite#1696datlechin wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dac4060657
ℹ️ 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".
| supportsAddIndex: driverType.supportsAddIndex, | ||
| supportsDropIndex: driverType.supportsDropIndex, | ||
| supportsModifyPrimaryKey: driverType.supportsModifyPrimaryKey, | ||
| supportsTriggers: driverType.supportsTriggers, |
There was a problem hiding this comment.
Avoid reading new DriverPlugin witnesses from stale plugins
For third-party drivers compiled against the previous PluginKit, this new DriverPlugin requirement has no witness-table entry; this method already avoids supportsColumnReorder for exactly that reason. Accessing driverType.supportsTriggers while registering such a plugin can crash or reject the plugin before it can fall back to the default false, so existing installed drivers are not actually compatible with this additive change.
Useful? React with 👍 / 👎.
| WHEN (t.tgtype & 8) != 0 THEN 'UPDATE' | ||
| WHEN (t.tgtype & 16) != 0 THEN 'DELETE' |
There was a problem hiding this comment.
Decode PostgreSQL UPDATE/DELETE trigger bits correctly
PostgreSQL's tgtype uses bit 8 for DELETE and bit 16 for UPDATE, but these branches label them the other way around. Any single-event UPDATE trigger will be shown as DELETE, and DELETE triggers as UPDATE, with the same mix-up in the multi-event labels above.
Useful? React with 👍 / 👎.
| selectedName: $selectedTriggerName, | ||
| fontSize: $ddlFontSize, | ||
| databaseType: connection.type, | ||
| isLoading: !loadedTabs.contains(.triggers) |
There was a problem hiding this comment.
Stop leaving the triggers tab loading after fetch errors
When fetchTriggers throws (for example after a dropped connection or catalog permission error), fetchTabData only logs the error and does not insert .triggers into loadedTabs or surface an error. Because the new view's loading state is derived solely from !loadedTabs.contains(.triggers), the Triggers tab stays on ProgressView indefinitely instead of showing an error or an empty/retryable state.
Useful? React with 👍 / 👎.
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 531b4552b6
ℹ️ 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".
| } | ||
|
|
||
| var supportsTriggers: Bool { | ||
| PluginMetadataRegistry.shared.snapshot(forTypeId: pluginTypeId)?.capabilities.supportsTriggers ?? false |
There was a problem hiding this comment.
Keep trigger support type-specific
When the connection type is an alias such as Redshift or CockroachDB, pluginTypeId resolves to PostgreSQL, so this reads PostgreSQL's supportsTriggers = true instead of the alias snapshot. I checked the variant drivers returned from PostgreSQLPlugin.createDriver; RedshiftPluginDriver and CockroachPluginDriver do not implement fetchTriggers, so those connections now expose a Triggers tab that can only show the default empty result rather than being hidden. Please read the type-specific snapshot or preserve per-variant support here.
Useful? React with 👍 / 👎.
Closes #1695
What
Adds a read-only Triggers tab to the table Show Structure view, alongside Columns / Indexes / Foreign Keys / DDL. It lists each trigger (name, timing, event) and shows the full definition SQL in the existing read-only syntax-highlighted viewer with a Copy button.
Available for MySQL, MariaDB, PostgreSQL, and SQLite. The tab is hidden for databases that don't expose triggers.
Why this shape
The trigger body SQL is the point of the feature, so it renders in a master-detail layout (selectable list + full definition pane) rather than as a clipped grid cell. This reuses the read-only
DDLTextView, following the precedent the.ddland.partstabs already set: read-only tabs bypass the editableDataGridViewpath.Read-only for v1, matching Beekeeper Studio's model and avoiding the edit/localization bugs the editable tools (TablePlus, Sequel Ace) have hit.
How it's wired
PluginTriggerInfo;fetchTriggersonPluginDatabaseDriverwith a default{ [] };supportsTriggersonDriverPlugindefaultingfalse.TriggerInfomodel;fetchTriggersonDatabaseDriver(default[]) +PluginDriverAdapterbridge;supportsTriggerscapability viaPluginMetadataRegistry+DatabaseType.information_schema.TRIGGERS), PostgreSQL (pg_trigger+pg_get_triggerdef, handles multi-event triggers and skips internal ones), SQLite (sqlite_masterwith token-based timing/event parse).StructureTab.triggers, newTriggerDetailView, lazy fetch,availableTabsfilter, count badge, and.triggersno-op cases across the grid delegate / row provider / change manager.Registry-only plugins inherit the empty default, so no plugin rebuild is needed. Plugins like Oracle/MSSQL can add trigger support later per-plugin without an ABI bump.
Tests
PluginTriggerInfoCodable round-trips (with and without a WHEN clause)PluginDriverAdapter.fetchTriggersmapping through a stub driverStructureTab.triggerspresence and display nameStructureGridDelegateadd/delete are no-ops on the triggers tabDocs
docs/features/table-structure.mdx[Unreleased] / AddedentryVerification
SwiftLint
--strictclean on all changed lines. Build extracted the new string-catalog keys (Triggers,No triggers).