Skip to content

feat(#311): introspect schemas in mssql driver - #312

Open
reenigneEsrever92 wants to merge 1 commit into
0xErwin1:mainfrom
reenigneEsrever92:feat/mssql-schemas
Open

feat(#311): introspect schemas in mssql driver#312
reenigneEsrever92 wants to merge 1 commit into
0xErwin1:mainfrom
reenigneEsrever92:feat/mssql-schemas

Conversation

@reenigneEsrever92

@reenigneEsrever92 reenigneEsrever92 commented Jul 30, 2026

Copy link
Copy Markdown

Summary

Added schema introspection for mssql databases.

What does this resolve?

How was this solved?

If schemas are present for a connection build child tree nodes using Sidebar::build_schema_children.

Validation

  • Run dbflux
  • Connect to a mssql database
  • Open a database node
  • Schemas are now shown in blue with a stack icon

Where was this tested?

  • Local development environment
  • Automated tests
  • Linux
  • macOS
  • Windows
  • X11
  • Wayland
  • Other:

Checklist

  • I verified the change against the affected user flow(s)
  • I added or updated tests when needed
  • I documented follow-up work or known limitations when applicable
  • I updated CHANGELOG.md under ## [Unreleased] if this is user-visible
  • I applied the appropriate labels (see CONTRIBUTING.md)

Labels to apply

driver:feature
ui:feature

@0xErwin1

Copy link
Copy Markdown
Owner

Thanks for taking this one on, the schema nodes are a real gap for MSSQL. A few things to sort out before this can land.

1. It doesn't compile against current main. The branch is based on d3359961, and TableInfo gained a storage_hints field in #309. Merging main in and running cargo check -p dbflux_driver_mssql gives:

error[E0063]: missing field `storage_hints` in initializer of `TableInfo`
    --> crates/dbflux_driver_mssql/src/driver.rs:3126:23

Rebasing on main should be enough to surface it locally.

2. The sidebar branch reads the wrong schema source. MSSQL is LazyPerDatabase, so the new else if !schema.schemas().is_empty() arm sits in the lazy path where db_schema (the per-database snapshot just fetched via schema_for_database) is already in hand, but it passes the connection-level schema instead. That snapshot only ever holds the schemas of the database that was current at connect time: FetchDatabaseSchemaParams::execute returns a DbSchemaInfo, and apply_database_refresh_outcome stores it under database_schemas with schema: None, so the connection snapshot is never refreshed.

Practical effect on a server with more than one database: expand AppDb and you get the initial database's schemas and tables rendered under it, with target_database = Some("AppDb"), so clicking a table opens a path that may not exist. The correctly fetched db_schema is dropped. It looks right in single-database testing, which is probably why it passed the manual check.

Since schema_for_database already tags every TableInfo / ViewInfo with its schema name, my suggestion is to keep the fix entirely in build_db_schema_content and group that single DbSchemaInfo's tables and views by their schema field into schema nodes. That stays driver-agnostic, fixes it for every LazyPerDatabase driver at once, and makes the driver.rs change unnecessary.

3. fetch_db_schemas(db).unwrap_or_default() swallows the error. Per CLAUDE.md a fallible result shouldn't be silently discarded, .log_err() is the minimum here. Worth noting this also runs the same two sys.tables / sys.views queries that schema_for_database already runs, so it's two extra round-trips on every connect for data the lazy path fetches anyway.

Happy to look again once the rebase and the schema-source question are settled.

@reenigneEsrever92

Copy link
Copy Markdown
Author

I see. Thanks for the response. Grouping as you described under point 2 would be done in the sidebar?

@0xErwin1

Copy link
Copy Markdown
Owner

Yes, entirely in the sidebar: crates/dbflux_ui_sidebar/src/tree_builder.rs, no driver or core change needed.

Concretely, in the lazy branch of resolve_db_children (where you currently added the else if), take the db_schema you already have and split it into one DbSchemaInfo per distinct schema value across its tables and views, then call build_db_schema_content once per group. That is the same shape build_schema_children already uses when it iterates snapshot.schemas(), so the resulting tree matches what the non-lazy path produces.

Two things worth knowing while you do it:

  • It also fixes the cache keys. build_db_schema_content builds SchemaCacheKey::new(database_name, Some(schema_name)) from db_schema.name, which today is the database name on the lazy path, so types/indexes/FKs/routines are cached under a schema that doesn't exist. Grouping by the real schema makes those keys correct for free.
  • Keep the single-group case rendering exactly as it does now. MySQL is also LazyPerDatabase and its fetch_tables_shallow sets schema: Some(database) on every table, so it collapses to one group named after the database and comes out unchanged.

A unit test next to build_db_schema_content_uses_per_table_schema_when_present covering the multi-schema case would be a good place to pin the behavior.

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.

[feature] Schemas for MSSQL Database

2 participants