Skip to content

Commit b055926

Browse files
committed
feat: update changelog for version 0.19.13 and implement save prompt for unsaved changes in untitled queries
1 parent 8419f80 commit b055926

3 files changed

Lines changed: 59 additions & 48 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ All notable changes to the MS SQL Manager extension will be documented in this f
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.19.13] - 2026-05-29
9+
10+
### Changed
11+
12+
- **New Query — Now prompts to save unsaved changes on close**
13+
- "New Query" (untitled queries) now open as VS Code untitled documents through the custom SQL editor, instead of raw webview panels.
14+
- Closing an untitled query that has been edited now shows VS Code's native "Do you want to save the changes?" dialog with Save / Don't Save / Cancel options.
15+
- Save triggers a Save As dialog to pick a `.sql` file location, then continues editing in the custom editor.
16+
- Empty untitled queries (no content typed) can still be closed without a prompt.
17+
- Auto-execute and query history info are preserved when opening untitled queries from tree commands.
18+
819
## [0.19.12] - 2026-05-29
920

1021
### Fixed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "ms-sql-manager",
33
"displayName": "MS SQL Manager",
44
"description": "Manage Microsoft SQL Server databases with connection management, schema browsing, and query execution.",
5-
"version": "0.19.12",
5+
"version": "0.19.13",
66
"publisher": "jakubkozera",
77
"icon": "ms-sql-manager.png",
88
"sponsor": {

src/sqlEditorProvider.ts

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ export class SqlEditorProvider implements vscode.CustomTextEditorProvider {
2222
private sqlSnippets: any[] = [];
2323
// Schema cache instance
2424
private schemaCache: SchemaCache;
25+
// Pending options for the next resolveCustomTextEditor call (auto-execute, history info)
26+
private pendingEditorOptions: { autoExecute?: boolean; historyInfo?: Record<string, unknown> } | null = null;
27+
// Counter for unique untitled query names
28+
private untitledCounter = 0;
2529

2630
constructor(
2731
private readonly context: vscode.ExtensionContext,
@@ -126,8 +130,22 @@ export class SqlEditorProvider implements vscode.CustomTextEditorProvider {
126130
// Send initial connections list
127131
this.updateConnectionsList(webviewPanel.webview);
128132

129-
// Note: Auto-execute is now controlled by the newQuery command via triggerAutoExecute()
130-
// to give explicit control over when queries execute
133+
// Handle pending options (auto-execute, history info) for untitled queries
134+
// opened via openUntitledQuery → CustomTextEditorProvider path
135+
if (this.pendingEditorOptions) {
136+
const opts = this.pendingEditorOptions;
137+
this.pendingEditorOptions = null;
138+
139+
if (opts.historyInfo) {
140+
webviewPanel.webview.postMessage({ type: 'historyInfo', ...opts.historyInfo });
141+
}
142+
143+
if (opts.autoExecute && document.getText().trim()) {
144+
setTimeout(() => {
145+
webviewPanel.webview.postMessage({ type: 'autoExecuteQuery' });
146+
}, 200);
147+
}
148+
}
131149
break;
132150

133151
case 'contentChanged':
@@ -1946,71 +1964,53 @@ COMMIT TRANSACTION;
19461964
}
19471965

19481966
/**
1949-
* Open an untitled SQL query webview panel (not backed by a file).
1950-
* When the user presses Ctrl+S the content is saved to a .sql file and
1951-
* re-opened in the normal CustomTextEditor.
1967+
* Open an untitled SQL query in the custom text editor.
1968+
* Uses VS Code's native untitled document support for proper dirty-state
1969+
* tracking and save prompts on close.
19521970
*/
19531971
public async openUntitledQuery(
19541972
connectionId: string,
19551973
databaseName?: string,
19561974
initialQuery?: string,
19571975
autoExecute: boolean = false,
19581976
historyInfo?: Record<string, unknown>
1959-
): Promise<vscode.WebviewPanel> {
1960-
// Get connection config to determine base title
1977+
): Promise<vscode.WebviewPanel | undefined> {
1978+
// Store connection preference so resolveCustomTextEditor picks it up
1979+
this.connectionProvider.setNextEditorPreferredDatabase(connectionId, databaseName || 'master');
1980+
1981+
// Store auto-execute and history info for the pending resolveCustomTextEditor call
1982+
if (autoExecute || historyInfo) {
1983+
this.pendingEditorOptions = { autoExecute, historyInfo };
1984+
}
1985+
1986+
// Build a meaningful title based on connection/database
19611987
const config = this.connectionProvider.getConnectionConfig(connectionId);
19621988
let baseTitle = 'Query';
19631989
if (config) {
19641990
if (config.connectionType === 'database') {
1965-
// Database connection - use connection name
19661991
baseTitle = `Query - ${config.name}`;
19671992
} else {
1968-
// Server connection - use database name
19691993
baseTitle = databaseName ? `Query - ${databaseName}` : `Query - ${config.name}`;
19701994
}
19711995
}
19721996

1973-
// Find unique title (adds counter if needed)
1974-
const uniqueTitle = this.getUniqueUntitledTitle(baseTitle);
1975-
1976-
const panel = vscode.window.createWebviewPanel(
1977-
'mssqlManager.sqlEditorUntitled',
1978-
uniqueTitle,
1979-
vscode.ViewColumn.One,
1980-
{
1981-
enableScripts: true,
1982-
retainContextWhenHidden: true,
1983-
localResourceRoots: [
1984-
vscode.Uri.joinPath(this.context.extensionUri, 'webview'),
1985-
vscode.Uri.joinPath(this.context.extensionUri, 'resources')
1986-
]
1987-
}
1988-
);
1989-
1990-
// Set icon with light/dark theme variants
1991-
panel.iconPath = {
1992-
light: vscode.Uri.joinPath(this.context.extensionUri, 'resources', 'icons', 'database-light.svg'),
1993-
dark: vscode.Uri.joinPath(this.context.extensionUri, 'resources', 'icons', 'database-dark.svg')
1994-
};
1995-
1996-
// Track this panel for unique title management
1997-
this.untitledPanels.set(panel, baseTitle);
1998-
1999-
// In-memory content buffer
2000-
let currentContent = initialQuery || '';
2001-
const compositeId = databaseName ? `${connectionId}::${databaseName}` : connectionId;
1997+
// Create an untitled document with a named URI for a meaningful tab title
1998+
this.untitledCounter++;
1999+
const untitledUri = vscode.Uri.parse(`untitled:${baseTitle}${this.untitledCounter > 1 ? ` (${this.untitledCounter})` : ''}.sql`);
2000+
const doc = await vscode.workspace.openTextDocument(untitledUri);
20022001

2003-
// Track this webview like a regular editor
2004-
const syntheticUri = vscode.Uri.parse(`untitled:query-${Date.now()}`);
2005-
this.webviewToDocument.set(panel.webview, syntheticUri);
2006-
this.webviewSelectedConnection.set(panel.webview, compositeId);
2002+
// Set initial content if provided
2003+
if (initialQuery) {
2004+
const edit = new vscode.WorkspaceEdit();
2005+
edit.insert(doc.uri, new vscode.Position(0, 0), initialQuery);
2006+
await vscode.workspace.applyEdit(edit);
2007+
}
20072008

2008-
panel.webview.html = this.getReactHtmlForWebview(panel.webview);
2009+
// Open it with our custom SQL editor
2010+
await vscode.commands.executeCommand('vscode.openWith', doc.uri, SqlEditorProvider.viewType);
20092011

2010-
// Setup state for serialization/restoration
2011-
this.setupUntitledPanelHandlers(panel, connectionId, databaseName, initialQuery || '', autoExecute, historyInfo);
2012-
2013-
return panel;
2012+
this.outputChannel.appendLine(`[SqlEditorProvider] Opened untitled query via CustomTextEditor for ${connectionId}::${databaseName || 'master'}`);
2013+
return undefined;
20142014
}
20152015

20162016
/**

0 commit comments

Comments
 (0)