Skip to content

Conversation

@aasimkhan30
Copy link
Contributor

@aasimkhan30 aasimkhan30 commented Feb 5, 2026

Description

Fixes: #20357

This PR implements a URI ownership coordination system between the MSSQL and PostgreSQL VS Code extensions. When both extensions are installed, they now coordinate to ensure only one extension shows UI elements (status bar, CodeLens) for a given SQL file at a time, based on which extension has an active connection to that file.

Problem

When both MSSQL and PostgreSQL extensions are installed, users experienced:

  • Duplicate status bar items (both extensions showing "Connect" or connection status)
  • Duplicate CodeLens prompts at the top of SQL files
  • Confusion about which extension is managing a particular SQL file
  • Ability to accidentally run commands against the wrong database type

Solution

Implemented a UriOwnershipCoordinator that:

  1. Exposes an API (uriOwnershipApi) for other extensions to query URI ownership
  2. Listens for ownership changes from coordinating extensions
  3. Hides UI elements when another extension owns the active file
  4. Shows informative messages when users try to use commands on files owned by another extension

Behavior

Scenario MSSQL UI PostgreSQL UI Screenshot
File not connected to either Show Shown image
File connected to MSSQL Shown Hidden image
File connected to PostgreSQL Hidden Shown image

User-Facing Messages

When a user tries to connect or run a query on a file connected to PostgreSQL through commands:

"This file is currently connected to PostgreSQL. Please disconnect from PostgreSQL before proceeding."

Backward Compatibility

  • ✅ Works normally if PostgreSQL extension is not installed
  • ✅ Works normally if PostgreSQL extension doesn't have uriOwnershipApi (older version)
  • ✅ No breaking changes to existing MSSQL functionality
  • ✅ Graceful degradation - both extensions work independently if coordination unavailable

Code Changes Checklist

  • New or updated unit tests added
  • All existing tests pass (npm run test)
  • Code follows contributing guidelines
  • Telemetry/logging updated if relevant
  • No regressions or UX breakage

Reviewers: Please read our reviewer guidelines

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a URI ownership coordination system between the MSSQL and PostgreSQL VS Code extensions to prevent duplicate UI elements (status bar items, CodeLens, editor buttons) when both extensions are installed. The coordination is achieved through a shared API that allows extensions to query which extension owns a given file URI.

Changes:

  • Introduced UriOwnershipCoordinator class to manage coordination with other database extensions
  • Added command name suffixes "(MSSQL)" to disambiguate from PostgreSQL commands in the command palette
  • Implemented UI hiding logic in status bar, CodeLens, and editor menus based on URI ownership

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
extensions/mssql/src/uriOwnership.ts New coordinator class that manages URI ownership API and listens for ownership changes from other extensions
extensions/mssql/typings/vscode-mssql.d.ts Added UriOwnershipApi interface to the public API
extensions/mssql/src/extension.ts Instantiates and initializes the URI ownership coordinator
extensions/mssql/src/views/statusView.ts Hides status bar items when active file is owned by another extension
extensions/mssql/src/queryResult/sqlCodeLensProvider.ts Hides CodeLens when URI is owned by another extension
extensions/mssql/package.json Added context-based visibility conditions to editor menu commands
extensions/mssql/src/controllers/mainController.ts Added ownership checks to prevent command execution on files owned by other extensions
extensions/mssql/src/constants/locConstants.ts Added localized error message for files owned by other extensions
extensions/mssql/package.nls.json Updated command titles with "(MSSQL)" suffix
localization/xliff/vscode-mssql.xlf Updated localization resources
extensions/mssql/l10n/bundle.l10n.json Updated l10n bundle with new messages
Comments suppressed due to low confidence (2)

extensions/mssql/package.json:440

  • For defensive programming and consistency, consider adding the !mssql.hideUIElements condition to other MSSQL-specific commands in the editor/title menu (disconnect, changeConnection, changeDatabase, showEstimatedPlan, etc.), not just runQuery and connect. While the resource in mssql.connections check should prevent these buttons from showing when a file is owned by another extension, adding the explicit hideUIElements check would provide an extra layer of protection against potential race conditions during connection handoff between extensions.
            "editor/title": [
                {
                    "command": "mssql.runQuery",
                    "when": "editorLangId == sql && !isInDiffEditor && resourcePath not in mssql.runningQueries && !mssql.hideUIElements",
                    "group": "navigation@1"
                },
                {
                    "command": "mssql.cancelQuery",
                    "when": "editorLangId == sql && !isInDiffEditor && resourcePath in mssql.runningQueries",
                    "group": "navigation@2"
                },
                {
                    "command": "mssql.revealQueryResult",
                    "when": "editorLangId == sql && resource in mssql.connections && !isInDiffEditor",
                    "group": "navigation@2"
                },
                {
                    "command": "mssql.connect",
                    "when": "editorLangId == sql && !isInDiffEditor && resource not in mssql.connections && !mssql.hideUIElements",
                    "group": "navigation@3"
                },
                {
                    "command": "mssql.disconnect",
                    "when": "editorLangId == sql && !isInDiffEditor && resource in mssql.connections && resourcePath not in mssql.runningQueries",
                    "group": "navigation@3"
                },
                {
                    "command": "mssql.changeConnection",
                    "when": "editorLangId == sql && !isInDiffEditor && resource in mssql.connections && resourcePath not in mssql.runningQueries",
                    "group": "navigation@4"
                },
                {
                    "command": "mssql.changeDatabase",
                    "when": "editorLangId == sql && !isInDiffEditor && resource in mssql.connections && resourcePath not in mssql.runningQueries",
                    "group": "navigation@5"
                },
                {
                    "command": "mssql.showEstimatedPlan",
                    "when": "editorLangId == sql && !isInDiffEditor && resource in mssql.connections && resourcePath not in mssql.runningQueries",
                    "group": "navigation@10"
                },
                {
                    "command": "mssql.enableActualPlan",
                    "when": "editorLangId == sql && !isInDiffEditor && resource in mssql.connections && (resource not in mssql.executionPlan.urisWithActualPlanEnabled) && (resourcePath not in mssql.runningQueries)",
                    "group": "navigation@11"
                },
                {
                    "command": "mssql.disableActualPlan",
                    "when": "editorLangId == sql && !isInDiffEditor && resource in mssql.connections && (resource in mssql.executionPlan.urisWithActualPlanEnabled) && (resourcePath not in mssql.runningQueries)",
                    "group": "navigation@12"
                }

extensions/mssql/src/controllers/mainController.ts:241

  • The cmdChangeConnection command handler doesn't check for URI ownership like cmdConnect and cmdRunQuery do. While the editor menu buttons are hidden via package.json conditions, users can still invoke this command from the command palette. If a file is owned by another extension (e.g., PostgreSQL), users could potentially invoke "Change Connection (MSSQL)" from the command palette and get unexpected behavior. Consider adding the same ownership check here for consistency.
            this.registerCommand(Constants.cmdChangeConnection);
            this._event.on(Constants.cmdChangeConnection, () => {
                void this.runAndLogErrors(this.onNewConnection());
            });

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

PR Changes

Category Target Branch PR Branch Difference
vscode-mssql VSIX 5911 KB 5913 KB ⚪ 2 KB ( 0% )
sql-database-projects VSIX 7877 KB 7877 KB ⚪ 0 KB ( 0% )
data-workspace VSIX 544 KB 544 KB ⚪ 0 KB ( 0% )

@codecov-commenter
Copy link

codecov-commenter commented Feb 5, 2026

Codecov Report

❌ Patch coverage is 35.29412% with 33 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.22%. Comparing base (8c2a6a9) to head (3bd3878).

Files with missing lines Patch % Lines
extensions/mssql/src/views/statusView.ts 30.43% 16 Missing ⚠️
extensions/mssql/src/extension.ts 30.00% 7 Missing ⚠️
extensions/mssql/src/controllers/mainController.ts 20.00% 4 Missing ⚠️
...sions/mssql/src/queryResult/sqlCodeLensProvider.ts 42.85% 4 Missing ⚠️
...nsions/mssql/src/controllers/sqlDocumentService.ts 66.66% 2 Missing ⚠️

❌ Your patch status has failed because the patch coverage (35.29%) is below the target coverage (70.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #21101      +/-   ##
==========================================
- Coverage   68.29%   68.22%   -0.08%     
==========================================
  Files         242      242              
  Lines       23543    23594      +51     
  Branches     3114     3127      +13     
==========================================
+ Hits        16078    16096      +18     
- Misses       7336     7369      +33     
  Partials      129      129              
Files with missing lines Coverage Δ
...nsions/mssql/src/controllers/sqlDocumentService.ts 86.15% <66.66%> (-0.62%) ⬇️
extensions/mssql/src/controllers/mainController.ts 17.51% <20.00%> (+0.01%) ⬆️
...sions/mssql/src/queryResult/sqlCodeLensProvider.ts 38.46% <42.85%> (+0.96%) ⬆️
extensions/mssql/src/extension.ts 22.00% <30.00%> (+0.88%) ⬆️
extensions/mssql/src/views/statusView.ts 40.19% <30.43%> (-0.80%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI review requested due to automatic review settings February 5, 2026 09:33
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated 8 comments.

Comments suppressed due to low confidence (1)

extensions/mssql/package.json:440

  • Several editor/title menu items that should be hidden when the URI is owned by another extension are missing the && !mssql.hideUIElements condition:
  • mssql.disconnect (line 413)
  • mssql.changeConnection (line 418)
  • mssql.changeDatabase (line 423)
  • mssql.revealQueryResult (line 403)
  • mssql.cancelQuery (line 398)
  • mssql.showEstimatedPlan (line 428)
  • mssql.enableActualPlan (line 433)
  • mssql.disableActualPlan (line 438)

These commands all operate on the active editor and should not be visible when the file is owned by a coordinating extension like PostgreSQL, for consistency with the mssql.runQuery and mssql.connect commands that already have this condition.

                {
                    "command": "mssql.cancelQuery",
                    "when": "editorLangId == sql && !isInDiffEditor && resourcePath in mssql.runningQueries",
                    "group": "navigation@2"
                },
                {
                    "command": "mssql.revealQueryResult",
                    "when": "editorLangId == sql && resource in mssql.connections && !isInDiffEditor",
                    "group": "navigation@2"
                },
                {
                    "command": "mssql.connect",
                    "when": "editorLangId == sql && !isInDiffEditor && resource not in mssql.connections && !mssql.hideUIElements",
                    "group": "navigation@3"
                },
                {
                    "command": "mssql.disconnect",
                    "when": "editorLangId == sql && !isInDiffEditor && resource in mssql.connections && resourcePath not in mssql.runningQueries",
                    "group": "navigation@3"
                },
                {
                    "command": "mssql.changeConnection",
                    "when": "editorLangId == sql && !isInDiffEditor && resource in mssql.connections && resourcePath not in mssql.runningQueries",
                    "group": "navigation@4"
                },
                {
                    "command": "mssql.changeDatabase",
                    "when": "editorLangId == sql && !isInDiffEditor && resource in mssql.connections && resourcePath not in mssql.runningQueries",
                    "group": "navigation@5"
                },
                {
                    "command": "mssql.showEstimatedPlan",
                    "when": "editorLangId == sql && !isInDiffEditor && resource in mssql.connections && resourcePath not in mssql.runningQueries",
                    "group": "navigation@10"
                },
                {
                    "command": "mssql.enableActualPlan",
                    "when": "editorLangId == sql && !isInDiffEditor && resource in mssql.connections && (resource not in mssql.executionPlan.urisWithActualPlanEnabled) && (resourcePath not in mssql.runningQueries)",
                    "group": "navigation@11"
                },
                {
                    "command": "mssql.disableActualPlan",
                    "when": "editorLangId == sql && !isInDiffEditor && resource in mssql.connections && (resource in mssql.executionPlan.urisWithActualPlanEnabled) && (resourcePath not in mssql.runningQueries)",
                    "group": "navigation@12"
                }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings February 5, 2026 09:50
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 13 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings February 6, 2026 00:16
manujoseph85
manujoseph85 previously approved these changes Feb 6, 2026
Copy link
Contributor

@manujoseph85 manujoseph85 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice if we can find a way to share this code with PG without duplicating the code. Coordinating fixes with them if we need changes would be a hassle

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 15 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings February 6, 2026 06:20
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 28 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings February 6, 2026 06:52
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 27 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +296 to +310
private _refreshCoordinatingExtensions(): void {
const newExtensions = discoverCoordinatingExtensions(this._context.extension.id);

// Find newly added extensions
for (const extInfo of newExtensions) {
if (!this._coordinatingExtensionApis.has(extInfo.extensionId)) {
const extension = vscode.extensions.getExtension(extInfo.extensionId);
if (extension?.isActive) {
this._registerCoordinatingExtensionApi(extInfo.extensionId, extension.exports);
}
}
}

this._coordinatingExtensions = newExtensions;
}
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The _refreshCoordinatingExtensions method does not handle the case where an extension is uninstalled or deactivated. When an extension is removed, it remains in _coordinatingExtensionApis Map and its event listener remains registered in context.subscriptions, potentially causing errors when the extension tries to call the API or when events fire. The method should check for removed extensions and clean up their entries from _coordinatingExtensionApis.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 6, 2026 07:08
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 28 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

[Bug]: mssql and postgres extension don't play nicely together

3 participants