Skip to content

Commit e00a427

Browse files
allancascanteAllan Cascante
andauthored
fix to lunch profiler on a on prem database having default database in the connection profile (#21626)
Co-authored-by: Allan Cascante <acascante@microsoft.com>
1 parent d586a0b commit e00a427

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

extensions/mssql/src/profiler/profilerController.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,21 @@ export class ProfilerController {
110110
// Azure sessions are already database-scoped via ON DATABASE,
111111
// so skip the client-side DatabaseName filter entirely.
112112
databaseScopeFilter = undefined;
113+
} else {
114+
// On-prem XEvent sessions use ON SERVER (server-scoped).
115+
// If the connection profile has a specific database, clear it so the STS
116+
// connects at server level; otherwise the STS may look for the session
117+
// in the database scope and fail with "session not found".
118+
// Preserve the database as a client-side filter if one isn't already set.
119+
if (profileToUse.database && !this.isSystemDatabase(profileToUse.database)) {
120+
if (!databaseScopeFilter) {
121+
databaseScopeFilter = profileToUse.database;
122+
}
123+
profileToUse = { ...profileToUse, database: "" };
124+
this._logger.verbose(
125+
`Cleared database from on-prem profile to ensure server-scoped session (filter: ${databaseScopeFilter})`,
126+
);
127+
}
113128
}
114129

115130
// Generate a unique URI for this profiler connection

extensions/mssql/test/unit/profiler/profilerController.test.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,107 @@ suite("ProfilerController Server Type Tests", () => {
956956
expect(connectionManager.disconnect.called).to.be.true;
957957
});
958958

959+
test("should clear database from on-prem profile when default database is set", async () => {
960+
// On-prem XEvent sessions use ON SERVER (server-scoped).
961+
// If the connection profile has a default (user) database, the database
962+
// must be cleared so the STS connects at server level.
963+
const mockTreeNodeInfo = {
964+
connectionProfile: {
965+
server: "localhost",
966+
authenticationType: "SqlLogin",
967+
user: "testuser",
968+
password: "testpass",
969+
database: "MyUserDB", // Default database set in connection
970+
},
971+
};
972+
973+
const mockTemplateItem = {
974+
label: "Standard",
975+
description: "Standard profiler template",
976+
detail: "Engine: Standalone",
977+
template: {
978+
id: "Standard_OnPrem",
979+
name: "Standard",
980+
defaultView: "Standard View",
981+
createStatement: "CREATE EVENT SESSION",
982+
},
983+
};
984+
985+
showQuickPickStub.resolves(mockTemplateItem);
986+
(vscode.window.showInputBox as sinon.SinonStub).resolves("Standard_OnPrem");
987+
profilerService.getXEventSessions.resolves({ sessions: [] });
988+
989+
profilerService.onSessionCreated.callsFake(
990+
(_ownerUri: string, handler: (params: unknown) => void) => {
991+
setTimeout(() => {
992+
handler({ sessionName: "Standard_OnPrem", templateName: "Standard" });
993+
}, 10);
994+
return { dispose: sandbox.stub() };
995+
},
996+
);
997+
998+
createController();
999+
const launchCommand = registeredCommands.get("mssql.profiler.launchFromObjectExplorer");
1000+
1001+
await launchCommand!(mockTreeNodeInfo);
1002+
1003+
// The connect call should have an empty database (cleared for server-scoped session)
1004+
expect(connectionManager.connect).to.have.been.called;
1005+
const connectArgs = connectionManager.connect.getCall(0).args;
1006+
const usedProfile = connectArgs[1];
1007+
expect(usedProfile.database).to.equal("");
1008+
});
1009+
1010+
test("should not clear system database from on-prem profile", async () => {
1011+
// If the on-prem connection is to a system database (e.g. master),
1012+
// there's no need to clear it — server-scoped sessions work fine from master.
1013+
const mockTreeNodeInfo = {
1014+
connectionProfile: {
1015+
server: "localhost",
1016+
authenticationType: "SqlLogin",
1017+
user: "testuser",
1018+
password: "testpass",
1019+
database: "master",
1020+
},
1021+
};
1022+
1023+
const mockTemplateItem = {
1024+
label: "Standard",
1025+
description: "Standard profiler template",
1026+
detail: "Engine: Standalone",
1027+
template: {
1028+
id: "Standard_OnPrem",
1029+
name: "Standard",
1030+
defaultView: "Standard View",
1031+
createStatement: "CREATE EVENT SESSION",
1032+
},
1033+
};
1034+
1035+
showQuickPickStub.resolves(mockTemplateItem);
1036+
(vscode.window.showInputBox as sinon.SinonStub).resolves("Standard_OnPrem");
1037+
profilerService.getXEventSessions.resolves({ sessions: [] });
1038+
1039+
profilerService.onSessionCreated.callsFake(
1040+
(_ownerUri: string, handler: (params: unknown) => void) => {
1041+
setTimeout(() => {
1042+
handler({ sessionName: "Standard_OnPrem", templateName: "Standard" });
1043+
}, 10);
1044+
return { dispose: sandbox.stub() };
1045+
},
1046+
);
1047+
1048+
createController();
1049+
const launchCommand = registeredCommands.get("mssql.profiler.launchFromObjectExplorer");
1050+
1051+
await launchCommand!(mockTreeNodeInfo);
1052+
1053+
// The connect call should keep the database as "master"
1054+
expect(connectionManager.connect).to.have.been.called;
1055+
const connectArgs = connectionManager.connect.getCall(0).args;
1056+
const usedProfile = connectArgs[1];
1057+
expect(usedProfile.database).to.equal("master");
1058+
});
1059+
9591060
test("should not prompt for database when Azure SQL launched from database node", async () => {
9601061
// When launching from a Database node on Azure, the databaseScopeFilter
9611062
// pre-fills connectionProfile.database so ensureAzureDatabaseSelected

0 commit comments

Comments
 (0)