Skip to content

Code review changes for SQL Notebooks#21439

Merged
lewis-sanchez merged 31 commits into
mainfrom
lewissanchez/sql-notebooks/code-review
Mar 5, 2026
Merged

Code review changes for SQL Notebooks#21439
lewis-sanchez merged 31 commits into
mainfrom
lewissanchez/sql-notebooks/code-review

Conversation

@lewis-sanchez
Copy link
Copy Markdown
Contributor

@lewis-sanchez lewis-sanchez commented Mar 4, 2026

Description

This PR addresses the code review feedback from this pull request: #21324

Provide a clear, concise summary of the changes in this PR. What problem does it solve? Why is it needed? Link any related issues using issue closing keywords.

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

The `NotebookConnectionManager.connectWith` method no longer performs a database mismatch check followed by a disconnect and reconnect.

Previously, if the actual database reported by the connection service (STS) differed from the database specified in the initial `IConnectionInfo`, the manager would attempt to reconnect to the correct database. This logic is now removed.

The manager now directly accepts the database reported by STS as the active database for the connection, simplifying the connection flow and avoiding unnecessary reconnect cycles. This prioritizes the actual connected database for internal state management.
Copy link
Copy Markdown
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

Follow-up changes to the SQL Notebooks feature to incorporate review feedback from #21324, including moving notebook execution onto STS query notifications, reusing shared result-grid behaviors in the notebook renderer, and aligning notebook UI strings with “MSSQL” branding/localization.

Changes:

  • Replaced notebook batch parsing + simple-query execution with an STS notification–driven NotebookQueryExecutor (query/executeString + subset fetching + cancel/dispose).
  • Reused the shared Query Result grid CellSelectionModel and shared table icon CSS in the notebook renderer; removed notebook-specific selection model.
  • Updated notebook-related localization strings (“MSSQL …”, “canceled”) and adjusted relevant unit tests.

Reviewed changes

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

Show a summary per file
File Description
localization/xliff/vscode-mssql.xlf Adds/updates notebook + cancellation trans-units and renames notebook strings to “MSSQL …”.
extensions/mssql/l10n/bundle.l10n.json Updates runtime l10n bundle keys for the renamed notebook strings and cancellation spelling.
extensions/mssql/src/constants/locConstants.ts Renames notebook status bar strings to “MSSQL …” and updates cancellation string to “canceled”.
extensions/mssql/src/notebooks/sqlNotebookController.ts Switches execution path to executeQueryString (single call) + batch-output formatting; supports DI factory for tests; updates naming to MSSQL.
extensions/mssql/src/notebooks/notebookQueryExecutor.ts New executor that wraps STS query notifications into a promise-based API, including subset row fetching and best-effort cancel/dispose.
extensions/mssql/src/notebooks/notebookConnectionManager.ts Uses STS-populated connection info for “actual database”, delegates execution to NotebookQueryExecutor, removes old simple-query DB verification/cancel path.
extensions/mssql/src/models/contracts/queryExecute.ts Adds QueryExecuteStringRequest + params for STS query/executeString.
extensions/mssql/src/controllers/queryNotificationHandler.ts Generalizes runner tracking to IQueryEventHandler (decouples from QueryRunner).
extensions/mssql/src/reactviews/pages/QueryResult/table/plugins/cellSelectionModel.plugin.ts Makes context/keybinding deps optional and adds a “basic keyboard support” fallback for notebook renderer usage.
extensions/mssql/src/reactviews/pages/NotebookRenderer/notebookResultGrid.tsx Switches to shared CellSelectionModel and imports shared table.css.
extensions/mssql/src/reactviews/pages/NotebookRenderer/notebookResultGrid.css Removes notebook-local button styling; adds notebook-specific overrides for shared sort/filter button classes.
extensions/mssql/src/reactviews/pages/NotebookRenderer/notebookHeaderMenu.plugin.ts Uses shared CSS-driven icons/classes instead of inline SVGs; toggles state via CSS classes.
extensions/mssql/src/reactviews/pages/NotebookRenderer/notebookContextMenu.plugin.ts Expands rationale comment describing why notebook context menu is separate from QueryResult context menu.
extensions/mssql/scripts/bundle-notebook-renderer.js Enhances CSS inlining to rewrite url() assets to inline data URIs for iframe renderer.
extensions/mssql/src/notebooks/notebookCodeLensProvider.ts Clarifies why “last active connection” logic doesn’t work for notebooks.
extensions/mssql/test/unit/sqlNotebookController.test.ts Updates controller tests to use a mocked NotebookConnectionManager + new result shape.
extensions/mssql/test/unit/notebookQueryExecutor.test.ts Adds unit tests for the new STS-notification based executor.
extensions/mssql/test/unit/notebookConnectionManager.test.ts Updates tests for new execution path and connection-info behavior.
extensions/mssql/test/unit/batchParser.test.ts Removes tests for deleted batch parser.
extensions/mssql/src/notebooks/batchParser.ts Removes batch parsing helper in favor of STS batch handling.
extensions/mssql/src/reactviews/pages/NotebookRenderer/notebookCellSelectionModel.plugin.ts Removes notebook-specific cell selection model in favor of shared implementation.
Comments suppressed due to low confidence (1)

extensions/mssql/src/notebooks/notebookConnectionManager.ts:133

  • promptAndConnect formats the connection label using actualDb, but then stores the original connectionInfo (which may still contain the requested/previous database). This can desync getCurrentDatabase() / future changeDatabase() calls from what STS actually opened. Store this.connectionInfo with the resolved actualDb (fallback to the profile DB if actualDb is "(unknown)").
            const actualDb = this.getActualDatabase(uri);
            this.log.info(`[promptAndConnect] Actual DB: ${actualDb}`);
            this.connectionLabel = formatConnectionLabel(connectionInfo.server, actualDb);

            this.connectionUri = uri;
            this.connectionInfo = connectionInfo;
            activity.end(ActivityStatus.Succeeded);

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

Comment on lines +207 to 214
// Get the actual database name from the connection info that STS populated
const actualDb = this.getActualDatabase(uri);
this.log.info(`[changeDatabase] Verified: ${actualDb}`);

this.connectionUri = uri;
this.connectionInfo = newInfo;
this.connectionLabel = formatConnectionLabel(newInfo.server, actualDb);
}
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

changeDatabase verifies the actual DB via getActualDatabase(uri) and uses it for connectionLabel, but it keeps this.connectionInfo = newInfo (the requested DB). This means getCurrentDatabase() can return a different DB than what the label/STS session is actually using. Update this.connectionInfo to reflect actualDb (with a sensible fallback when actualDb is "(unknown)").

Copilot uses AI. Check for mistakes.
Comment thread localization/xliff/vscode-mssql.xlf Outdated
Comment on lines +3634 to +3649
<trans-unit id="++CODE++65298a316736d0742788a35a1a44d804842b5f5d39234b03faa3be7815a545e4">
<source xml:lang="en">MSSQL Notebook connected to {0}</source>
<note>{0} is the connection label</note>
</trans-unit>
<trans-unit id="++CODE++99a3297c47d9336c0c32fe572074cba7cd53bf9b0d5988c14d3335dd468e2c37">
<source xml:lang="en">MSSQL: Not connected</source>
</trans-unit>
<trans-unit id="++CODE++845cd20358ee1964f66ca8b28c6df89c00d0f59d43a3e8e3f3d65a515194a1da">
<source xml:lang="en">MSSQL: Welcome &amp; What&apos;s New</source>
</trans-unit>
<trans-unit id="++CODE++2b136410190298a2840e44bf76dd88579edad1f2b56366e66685938b77821aa4">
<source xml:lang="en">MSSQL: click to change database</source>
</trans-unit>
<trans-unit id="++CODE++b42a988a00b3328f2d2a752321195c33513a2daafb555eac4dc97540e9978b5f">
<source xml:lang="en">MSSQL: click to connect</source>
</trans-unit>
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

New/updated trans-units were added here (notebook status bar + cancellation strings). In this repo, when adding/changing strings in vscode-mssql.xlf, the same trans-unit IDs should be mirrored into each localized vscode-mssql.<lang>.xlf to keep localization in sync; currently only the source XLF is updated.

Copilot uses AI. Check for mistakes.
Comment on lines +4684 to 4686
<trans-unit id="++CODE++2da839233749a1d48af0f1399da21768ade458db40ba95dcd405a7addefad753">
<source xml:lang="en">Query execution was canceled.</source>
</trans-unit>
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

This updated trans-unit ("Query execution was canceled.") also needs to be mirrored into each localized vscode-mssql.<lang>.xlf so non-English builds don’t fall behind when the source string changes.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 4, 2026

PR Changes

Category Target Branch PR Branch Difference
vscode-mssql VSIX 6390 KB 6390 KB ⚪ 0 KB ( 0% )
sql-database-projects VSIX 7024 KB 7024 KB ⚪ 0 KB ( 0% )
data-workspace VSIX 535 KB 535 KB ⚪ 0 KB ( 0% )

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 4, 2026

Codecov Report

❌ Patch coverage is 92.80742% with 31 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.79%. Comparing base (5bd4782) to head (ab29b03).
⚠️ Report is 15 commits behind head on main.

Files with missing lines Patch % Lines
...sions/mssql/src/notebooks/sqlNotebookController.ts 78.57% 24 Missing ⚠️
...sions/mssql/src/notebooks/notebookQueryExecutor.ts 97.02% 7 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #21439      +/-   ##
==========================================
+ Coverage   72.72%   72.79%   +0.06%     
==========================================
  Files         323      323              
  Lines       96228    96441     +213     
  Branches     5360     5364       +4     
==========================================
+ Hits        69985    70206     +221     
+ Misses      26243    26235       -8     
Files with missing lines Coverage Δ
extensions/mssql/src/constants/locConstants.ts 75.97% <100.00%> (-0.20%) ⬇️
.../mssql/src/controllers/queryNotificationHandler.ts 100.00% <100.00%> (ø)
...ensions/mssql/src/models/contracts/queryExecute.ts 90.78% <100.00%> (+0.54%) ⬆️
...ns/mssql/src/notebooks/notebookCodeLensProvider.ts 100.00% <100.00%> (ø)
...s/mssql/src/notebooks/notebookConnectionManager.ts 99.01% <100.00%> (+1.27%) ⬆️
...sions/mssql/src/notebooks/notebookQueryExecutor.ts 97.02% <97.02%> (ø)
...sions/mssql/src/notebooks/sqlNotebookController.ts 74.13% <78.57%> (+2.37%) ⬆️
🚀 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.

@Benjin
Copy link
Copy Markdown
Contributor

Benjin commented Mar 4, 2026

@lewis-sanchez can you give this a more descriptive PR title since that's what becomes the commit message?

@lewis-sanchez lewis-sanchez changed the title Code review follow up to #21324 Code review changes for SQL Notebooks Mar 4, 2026
Comment thread extensions/mssql/src/constants/locConstants.ts Outdated
Comment thread extensions/mssql/src/models/contracts/queryExecute.ts
Comment thread extensions/mssql/src/notebooks/notebookCodeLensProvider.ts
Comment thread extensions/mssql/src/notebooks/notebookConnectionManager.ts Outdated
Comment thread extensions/mssql/src/notebooks/notebookQueryExecutor.ts Outdated
Comment thread extensions/mssql/src/notebooks/sqlNotebookController.ts Outdated
Comment thread extensions/mssql/src/notebooks/sqlNotebookController.ts Outdated
Comment thread extensions/mssql/test/unit/notebookConnectionManager.test.ts Outdated
Comment thread extensions/mssql/test/unit/notebookConnectionManager.test.ts Outdated
Comment thread extensions/mssql/test/unit/notebookConnectionManager.test.ts Outdated
// so extracted CSS files would never be loaded.
// so extracted CSS files would never be loaded. Asset url() references (e.g. SVG
// icons) are resolved to data URIs so they work inside the iframe.
const inlineCssPlugin = {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Probably we should look into merging all the bundling files as there is a lot of repeated code.

"SQL Notebooks: click to change database",
);
public static statusBarClickToConnect = l10n.t("SQL Notebooks: click to connect");
public static statusBarNotConnected = l10n.t("MSSQL: Not connected");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

NIT: Maybe we shold keep the labels consistent with codelens.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good point. We should point to the same strings.

@@ -116,17 +124,9 @@ export class NotebookConnectionManager implements vscode.Disposable {
const uri = await this.connectInternal(connectionInfo);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Follow up task: Please dedup this with prompt and connect from query editor. We should dup this implementation.

const params = new QueryExecuteStringParams();
params.ownerUri = ownerUri;
params.query = query;
await this.client.sendRequest(QueryExecuteStringRequest.type, params);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How is this different than existing queryexecuteStatement?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lewis replied elsewhere, but it has to do with lack of multi-batch support

} catch (err: any) {
if (cancelled) {
execution.replaceOutput([
new vscode.NotebookCellOutput([
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please create a helper that send this to avoid dup code.

Copilot AI review requested due to automatic review settings March 4, 2026 23:02
@lewis-sanchez lewis-sanchez requested a review from Benjin March 4, 2026 23:06
Copy link
Copy Markdown
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 23 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 +128 to 132
this.log.info(`[promptAndConnect] Actual DB: ${actualDb}`);
this.connectionLabel = formatConnectionLabel(connectionInfo.server, actualDb);

this.connectionUri = uri;
this.connectionInfo = connectionInfo;
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

actualDb can be undefined (if getConnectionInfoFromUri hasn’t populated yet), but it’s passed directly into formatConnectionLabel(...). This can both (1) cause a TS type error under strictNullChecks and (2) show an incorrect label (falls back to “master”) even if the user selected a different database. Please fall back to connectionInfo.database when actualDb is undefined, and consider storing the actual DB back into this.connectionInfo for consistency.

Suggested change
this.log.info(`[promptAndConnect] Actual DB: ${actualDb}`);
this.connectionLabel = formatConnectionLabel(connectionInfo.server, actualDb);
this.connectionUri = uri;
this.connectionInfo = connectionInfo;
const effectiveDb = actualDb ?? connectionInfo.database;
this.log.info(`[promptAndConnect] Actual DB: ${actualDb}, Effective DB: ${effectiveDb}`);
this.connectionLabel = formatConnectionLabel(connectionInfo.server, effectiveDb);
this.connectionUri = uri;
this.connectionInfo = {
...connectionInfo,
database: effectiveDb,
};

Copilot uses AI. Check for mistakes.
Comment on lines 100 to 118
@@ -120,10 +111,9 @@ export class NotebookHeaderMenu<T extends Slick.SlickData> {
args.node.appendChild(sortBtn);
this._columnSortButtonMapping.set(column.id!, sortBtn);

// Filter button
// Filter button — uses shared slick-header-filterbutton class (icons via table.css)
const filterBtn = document.createElement("button");
filterBtn.className = "nb-filter-button";
filterBtn.innerHTML = FILTER_ICON;
filterBtn.className = "slick-header-filterbutton";
filterBtn.title = "Filter";
filterBtn.tabIndex = -1;
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

The sort/filter header buttons are icon-only and currently only set title. For accessibility (screen readers) they should also set an aria-label (QueryResult’s header filter buttons do this). Please add aria-label attributes (ideally localized) for both the sort and filter buttons.

Copilot uses AI. Check for mistakes.
Comment on lines +3636 to 3648
<note>{0} is the connection label</note>
</trans-unit>
<trans-unit id="++CODE++a2b41c1abaf1dcf9e0e3f2dfadc4649810e9b986a3c53eaed96f510ec49d0ccd">
<source xml:lang="en">MSSQL: Click to change database</source>
</trans-unit>
<trans-unit id="++CODE++f993c79609a3d00c82d5214040869fd0b15ab7404074bc3fcf8111fcc88c5d45">
<source xml:lang="en">MSSQL: Click to connect</source>
</trans-unit>
<trans-unit id="++CODE++99a3297c47d9336c0c32fe572074cba7cd53bf9b0d5988c14d3335dd468e2c37">
<source xml:lang="en">MSSQL: Not connected</source>
</trans-unit>
<trans-unit id="++CODE++845cd20358ee1964f66ca8b28c6df89c00d0f59d43a3e8e3f3d65a515194a1da">
<source xml:lang="en">MSSQL: Welcome &amp; What&apos;s New</source>
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

The new/updated notebook trans-units added here (e.g. “MSSQL Notebook connected…”, “MSSQL: Click to …”, “MSSQL: Not connected”) don’t appear to be mirrored into the localized localization/xliff/vscode-mssql.<lang>.xlf files. For example, vscode-mssql.de.xlf still contains the old sources like “SQL Notebook connected to {0}”. Please add equivalent trans-units (typically with <target state="new">…</target>) to each localized file to keep localization in sync.

Suggested change
<note>{0} is the connection label</note>
</trans-unit>
<trans-unit id="++CODE++a2b41c1abaf1dcf9e0e3f2dfadc4649810e9b986a3c53eaed96f510ec49d0ccd">
<source xml:lang="en">MSSQL: Click to change database</source>
</trans-unit>
<trans-unit id="++CODE++f993c79609a3d00c82d5214040869fd0b15ab7404074bc3fcf8111fcc88c5d45">
<source xml:lang="en">MSSQL: Click to connect</source>
</trans-unit>
<trans-unit id="++CODE++99a3297c47d9336c0c32fe572074cba7cd53bf9b0d5988c14d3335dd468e2c37">
<source xml:lang="en">MSSQL: Not connected</source>
</trans-unit>
<trans-unit id="++CODE++845cd20358ee1964f66ca8b28c6df89c00d0f59d43a3e8e3f3d65a515194a1da">
<source xml:lang="en">MSSQL: Welcome &amp; What&apos;s New</source>
<note>{0} is the connection label</note>
<target state="new">MSSQL Notebook connected to {0}</target>
</trans-unit>
<trans-unit id="++CODE++a2b41c1abaf1dcf9e0e3f2dfadc4649810e9b986a3c53eaed96f510ec49d0ccd">
<source xml:lang="en">MSSQL: Click to change database</source>
<target state="new">MSSQL: Click to change database</target>
</trans-unit>
<trans-unit id="++CODE++f993c79609a3d00c82d5214040869fd0b15ab7404074bc3fcf8111fcc88c5d45">
<source xml:lang="en">MSSQL: Click to connect</source>
<target state="new">MSSQL: Click to connect</target>
</trans-unit>
<trans-unit id="++CODE++99a3297c47d9336c0c32fe572074cba7cd53bf9b0d5988c14d3335dd468e2c37">
<source xml:lang="en">MSSQL: Not connected</source>
<target state="new">MSSQL: Not connected</target>
</trans-unit>
<trans-unit id="++CODE++845cd20358ee1964f66ca8b28c6df89c00d0f59d43a3e8e3f3d65a515194a1da">
<source xml:lang="en">MSSQL: Welcome &amp; What&apos;s New</source>
<target state="new">MSSQL: Welcome &amp; What&apos;s New</target>

Copilot uses AI. Check for mistakes.
Comment on lines +4684 to 4686
<trans-unit id="++CODE++2da839233749a1d48af0f1399da21768ade458db40ba95dcd405a7addefad753">
<source xml:lang="en">Query execution was canceled.</source>
</trans-unit>
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

This PR changes the cancellation string to “Query execution was canceled.”, but the localized vscode-mssql.<lang>.xlf files still appear to contain the previous source “Query execution was cancelled.” (e.g. vscode-mssql.de.xlf). Please mirror this updated trans-unit into each localized XLIFF so translations stay aligned with the base file.

Copilot uses AI. Check for mistakes.
database: "TestDB",
user: "sa",
password: "password",
email: undefined,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

for all these undefined props, you can just delete them and cast through unknown to clean this up. Also, better to have these sorts of helpers at the bottom of the file.

import { IDbColumn } from "../../../src/models/interfaces";

/** Creates a minimal but fully-typed IDbColumn for test data. */
function makeColumn(columnName: string, dataTypeName: string): IDbColumn {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

helper functions below test suites

sb.stub(vscode.window, "createStatusBarItem").returns(
mockStatusBarItem as unknown as vscode.StatusBarItem,
);
sb.stub(vscode.window, "createOutputChannel").returns({
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For the tests, you can/should just use stubVscodeWrapper().outputChannel here and the other places that you've created custom stubs for output channel

@lewis-sanchez lewis-sanchez merged commit e0d5b70 into main Mar 5, 2026
7 checks passed
@lewis-sanchez lewis-sanchez deleted the lewissanchez/sql-notebooks/code-review branch March 5, 2026 05:33
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.

5 participants