feat(sidebar): find tables in every schema from Open Quickly and the sidebar filter - #3060
Merged
Merged
Conversation
…atabase switches and dotted names
…database switches
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
… schema alphabetically in Open Quickly
…d the sidebar filter
This was referenced Sep 23, 2026
Signed-off-by: Ngô Quốc Đạt <datlechin@gmail.com>
This was referenced Sep 23, 2026
fix(windows): pin a screenshot window's size when it is built, not from inside its layout pass
#3092
Merged
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3048
Browsing
publicon PostgreSQL, neither Open Quickly nor the sidebar filter could findattendance.timesheet, and nothing acceptedattendance.timesheetorattendance.as a search.Root cause
.bySchemaengine (PostgreSQL, DuckDB) that holds the browsed schema only. On a.hierarchicalSchemaengine (Oracle, Snowflake, Trino) it is a snapshot taken at connect or refresh that a tree expansion never updates. Aschema.completion in the editor also widens it silently.fetchSchemas()andfetchTables(schema:).What changed
One listing, one owner.
PluginDatabaseDriver.fetchTablesInAllSchemas() -> [PluginTableInfo]?, defaulting tonil. Additive.currentPluginKitVersionis already 33 onmainwhile v0.75.0 shipped 32, so this reuses the pending number: no bump, noInfo.plistedits.table_schema IN (<listSchemas>). Same degradation ladder, partition exclusion, comments andinformation_schemaprivilege rules, so the two listings agree by construction. PGlite inherits it; Cockroach and Redshift fall back to the host.CatalogTableListingasks once, or schema by schema through one metadata scope, naming any schema whose read failed instead of reading it as empty.BackupScopeLoaderuses it too; it used to open a pooled connection per schema.DatabaseTreeMetadataServiceholds the result per database. Freshness is stale-while-revalidate (CatalogFreshness): a catalog change marks it stale and fetches nothing, because everyCOMMITreports a catalog change; the next reader refetches. A fetch that started before a change delivers its rows but cannot make the listing current.Open Quickly.
SchemaService(authoritative for the schemas it holds) and the all-schema listing (for the rest), and re-merge while the panel is open. TheSQLSchemaProviderdependency is gone.attendanceorattendance · View, including when selected and to VoiceOver.QualifiedSearchQueryreadsattendance.timesheet,attendance.,att.time,shop.attendance.timesheet, and"x",[x],`x`quoting. A dotted query is also scored as plain text, so a table namedb.cis still found.attendance., lists the schema alphabetically rather than shortest name first.Sidebar filter.
schema.tableandschema.work there too, with the sidebar's substring matching, in all three layouts. A table whose own name holds a dot still matches when its name is typed.Also fixed, in the code this rewrites:
fetchSchemasorfetchDatabasesfailed was cached and served on every reopen, never retried.tableItemIdjoined schema and name with an unescaped dot, soa."b.c"and"a.b".cshared one id. Dots and backslashes are now escaped, and every id without either is unchanged, so no Recent history is lost.main; the List layout's other-schema rows would have inherited it.Measured
On a local PostgreSQL 17.11 with 10,504 relations in 502 schemas, the all-schema listing takes 460 to 700 ms in one query, on a machine under load (load average above 30). The per-schema query takes 11 to 16 ms, about 6.5 s across all 502 before any network round trip.
scripts/check-postgres-table-listing-parity.shcompiles the plugin's real query builder and compares the two listings on every ladder rung. It uses a database with declarative partitions, a partition in another schema than its parent, legacy inheritance, a view, a materialized view, a foreign table, a schema the role cannot use, and quoted names with dots and mixed case:Tests
verify.sh build: pass, no new warnings in changed files.verify.sh plugins(AllPlugins): pass.verify.sh abi <merge-base>: the one diff isfetchTablesInAllSchemas()plus its default, which is additive.verify.sh docs: pass.--stricton every changed Swift file,shellcheck --severity=warningon the script: clean.QualifiedSearchQueryTests,SidebarSearchTests,CatalogFreshnessTests,CatalogTableListingTests,DatabaseTreeAllSchemaTablesTests,AllSchemaTablesDemandTests,DatabaseTreeFilterQualifiedSearchTests,QuickSwitcherCrossSchemaTests,PostgreSQLFetchTablesAllSchemasTests, plus new cases inDatabaseTreeCatalogRefreshPlanTests. Each suite's executed count was checked, since a suite added without regenerating the project compiles to nothing and still reports a pass.DatabaseTreeFilterTests,DatabaseTreeMetadataService*Tests,SidebarViewModel*Tests,SchemaService*Tests,CatalogChangeServiceTests,NativeDumpScopeTests,BackupScopeExpansionTestsand the PostgreSQL listing suites. After the third review: 343 of 343 pass.QuickSwitcherViewModelTestswaits a fixed 200 ms for its filter, and under a load average above 40 it failed intermittently in a 34-suite run. It passes 57/57 alone, after the third review too, and 157/157 beside every new suite.QuickSwitcherCrossSchemaTests,DatabaseTreeFilterQualifiedSearchTests,DatabaseTreeFilterTests,SidebarOutlineScaffoldTestsandQuickSwitcherViewModelTests, 134 of 134, the four new cases among them.No UI automation: the flow needs a PostgreSQL server with several schemas, UI tests run against the bundled SQLite sample, and plugins do not load under XCTest.
Before / After
A PostgreSQL 17 database with schemas
public,attendanceandpayroll, each holding atimesheet, browsingpublic. The after shots are from this branch's Debug build. No before build was captured: onmaineach of these shows thepublicrows alone, andattendance.shows nothing.Open Quickly,
timesheet. Before: one row. After: all three, the browsed schema first and the others named.Open Quickly,
attendance.. Before: no results. After: everything inattendance, alphabetically, the view named as one.Sidebar as List, filter
timesheet. Before:public.timesheetalone. After:attendanceandpayrollbelow it, opened to their match, their empty sections closed.Found while investigating, not changed here
Real, verified by reading the code path, and independent of this fix:
QuickSwitcherViewModel.swifthistory rows: an item's id is the newest execution's UUID, so picking a recent query and running it leaves its Recent entry pointing at an id that no longer exists. A few such picks empty the All scope's Recent list. Small.QuickSwitcherItem.tableItemIdandSharedSidebarState.commitTableOpen: frecency is keyed without the database, sopublic.usersopened inapp_prodshows in Recent and gets the boost after switching toapp_staging. Small, but changes stored ids.QuickSwitcherViewModel.makeCrossConnectionItems: the same table has one id in the All scope and another in the Connections scope, so Recent is split between them and each shows about half of its ten. Small.SQLSchemaProvider.swift:432(tableCompletionItems(inSchema:)thenmergeTables): afterattendance.completes once,FROM timesofferstimesheetand inserts it unqualified, which fails with relation "timesheet" does not exist. Medium.SchemaService.refreshLoadedSchemaObjects(:304) andSidebarTreeView.scheduleSearchLoad: on Oracle, Snowflake and other hierarchical engines, one search keystroke loads 2 to 4 queries per schema, and everyCOMMITreloads every loaded schema one after another. Medium.SchemaService.perSchemaStates(:50) is keyed without the database, so on Snowflake or Trino an in-place database switch shows the old database'sPUBLICtables under the new one until each schema reloads, and for good if that reload fails. Medium.TableInfo.id(QueryResult.swift:114) joins schema and name with an unescaped dot, soallLoadedTablesdrops one ofa."b.c"and"a.b".c. Small.PostgreSQLPluginDriver.swift:842and:867logerror.localizedDescriptionpublicly, which thepublic_error_text_in_logrule forbids.Plugins/sits outside SwiftLint'sincluded:, so nothing flags it. Small.Follow-ups this listing makes possible: single-call overrides for MSSQL, Oracle, DuckDB and Snowflake, which use the per-schema fallback today, and MCP
search_schemaacross every schema when noschemais given.Review
Three Codex passes read the diff, and every finding below is fixed here with a test unless it says otherwise.
shop.shop.orderscould not reach a schema named like its database; Open Quickly did not ask again for a listing that went stale while it was open. A fifth, dotted names colliding inallLoadedTables, reaches Open Quickly only through the hierarchical per-schema lists that the listing now outranks.Declined: the materialized-view and foreign-table arms check no per-object privilege. That is how the per-schema listing the sidebar already runs behaves,
pg_classnames are readable by every role, and changing it belongs with that listing.