mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Move query history into extension (#19794)
* initial * more * Remove connectionId * cleanup * cleanup * Remove core contributions, add to panel by default * Add enabled state * Update config * cleanup * Move * Remove newlines * update README
This commit is contained in:
@@ -3,15 +3,39 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import { QueryHistoryNode } from './queryHistoryNode';
|
||||
import { QueryHistoryProvider } from './queryHistoryProvider';
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext): Promise<void> {
|
||||
// Currently all the functionality for this is contained within the core ADS
|
||||
// code as the extensibility API doesn't currently support all the required
|
||||
// functionality (such as contributing tab panels)
|
||||
void vscode.commands.executeCommand('queryHistory.enableQueryHistory');
|
||||
}
|
||||
|
||||
export async function deactivate(): Promise<void> {
|
||||
|
||||
const provider = new QueryHistoryProvider();
|
||||
context.subscriptions.push(provider);
|
||||
context.subscriptions.push(vscode.window.registerTreeDataProvider('queryHistory', provider));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.open', async (node: QueryHistoryNode) => {
|
||||
return azdata.queryeditor.openQueryDocument(
|
||||
{
|
||||
content: node.queryText
|
||||
}, node.connectionProfile?.providerId);
|
||||
}));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.run', async (node: QueryHistoryNode) => {
|
||||
const doc = await azdata.queryeditor.openQueryDocument(
|
||||
{
|
||||
content: node.queryText
|
||||
}, node.connectionProfile?.providerId);
|
||||
await azdata.queryeditor.connect(doc.uri, node.connectionProfile?.connectionId || '');
|
||||
azdata.queryeditor.runQuery(doc.uri);
|
||||
}));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.delete', (node: QueryHistoryNode) => {
|
||||
provider.deleteNode(node);
|
||||
}));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.clear', () => {
|
||||
provider.clearAll();
|
||||
}));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.disableCapture', async () => {
|
||||
return provider.setCaptureEnabled(false);
|
||||
}));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('queryHistory.enableCapture', async () => {
|
||||
return provider.setCaptureEnabled(true);
|
||||
}));
|
||||
}
|
||||
|
||||
22
extensions/query-history/src/queryHistoryNode.ts
Normal file
22
extensions/query-history/src/queryHistoryNode.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import { removeNewLines } from './utils';
|
||||
|
||||
export class QueryHistoryNode extends vscode.TreeItem {
|
||||
constructor(
|
||||
public readonly queryText: string,
|
||||
public readonly connectionProfile: azdata.connection.ConnectionProfile | undefined,
|
||||
timestamp: Date,
|
||||
isSuccess: boolean
|
||||
) {
|
||||
super(removeNewLines(queryText), vscode.TreeItemCollapsibleState.None);
|
||||
this.iconPath = isSuccess ? new vscode.ThemeIcon('check', new vscode.ThemeColor('testing.iconPassed')) : new vscode.ThemeIcon('error', new vscode.ThemeColor('testing.iconFailed'));
|
||||
this.tooltip = queryText;
|
||||
this.description = connectionProfile ? `${connectionProfile.serverName}|${connectionProfile.databaseName} ${timestamp.toLocaleString()}` : timestamp.toLocaleString();
|
||||
}
|
||||
}
|
||||
80
extensions/query-history/src/queryHistoryProvider.ts
Normal file
80
extensions/query-history/src/queryHistoryProvider.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as azdata from 'azdata';
|
||||
import { QueryHistoryNode } from './queryHistoryNode';
|
||||
|
||||
const QUERY_HISTORY_CONFIG_SECTION = 'queryHistory';
|
||||
const CAPTURE_ENABLED_CONFIG_SECTION = 'captureEnabled';
|
||||
const DEFAULT_CAPTURE_ENABLED = true;
|
||||
|
||||
export class QueryHistoryProvider implements vscode.TreeDataProvider<QueryHistoryNode>, vscode.Disposable {
|
||||
|
||||
private _onDidChangeTreeData: vscode.EventEmitter<QueryHistoryNode | undefined> = new vscode.EventEmitter<QueryHistoryNode | undefined>();
|
||||
readonly onDidChangeTreeData: vscode.Event<QueryHistoryNode | undefined> = this._onDidChangeTreeData.event;
|
||||
|
||||
private _queryHistoryNodes: QueryHistoryNode[] = [];
|
||||
private _captureEnabled: boolean = true;
|
||||
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
|
||||
constructor() {
|
||||
this._disposables.push(azdata.queryeditor.registerQueryEventListener({
|
||||
onQueryEvent: async (type: azdata.queryeditor.QueryEventType, document: azdata.queryeditor.QueryDocument, args: azdata.ResultSetSummary | string | undefined, queryInfo?: azdata.queryeditor.IQueryInfo) => {
|
||||
if (this._captureEnabled && queryInfo && type === 'queryStop') {
|
||||
const queryText = queryInfo.queryText ?? '';
|
||||
const connProfile = await azdata.connection.getConnection(document.uri);
|
||||
const isError = queryInfo.messages.find(m => m.isError) ? false : true;
|
||||
// Add to the front of the list so the new item appears at the top
|
||||
this._queryHistoryNodes.unshift(new QueryHistoryNode(queryText, connProfile, new Date(), isError));
|
||||
this._onDidChangeTreeData.fire(undefined);
|
||||
}
|
||||
}
|
||||
}));
|
||||
this.updateCaptureEnabled();
|
||||
this._disposables.push(vscode.workspace.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration(QUERY_HISTORY_CONFIG_SECTION)) {
|
||||
this.updateCaptureEnabled();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public clearAll(): void {
|
||||
this._queryHistoryNodes = [];
|
||||
this._onDidChangeTreeData.fire(undefined);
|
||||
}
|
||||
|
||||
public deleteNode(node: QueryHistoryNode): void {
|
||||
this._queryHistoryNodes = this._queryHistoryNodes.filter(n => n !== node);
|
||||
this._onDidChangeTreeData.fire(undefined);
|
||||
}
|
||||
public getTreeItem(node: QueryHistoryNode): vscode.TreeItem {
|
||||
return node;
|
||||
}
|
||||
|
||||
public getChildren(element?: QueryHistoryNode): QueryHistoryNode[] {
|
||||
// We only have top level items
|
||||
return this._queryHistoryNodes;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this._disposables.forEach(d => d.dispose());
|
||||
}
|
||||
|
||||
private updateCaptureEnabled(): void {
|
||||
this._captureEnabled = vscode.workspace.getConfiguration(QUERY_HISTORY_CONFIG_SECTION).get(CAPTURE_ENABLED_CONFIG_SECTION) ?? DEFAULT_CAPTURE_ENABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether query history capture is currently enabled
|
||||
* @param enabled Whether capture is currently enabled
|
||||
* @returns A promise that resolves when the value is updated and persisted to configuration
|
||||
*/
|
||||
public async setCaptureEnabled(enabled: boolean): Promise<void> {
|
||||
this._captureEnabled = enabled;
|
||||
return vscode.workspace.getConfiguration(QUERY_HISTORY_CONFIG_SECTION).update(CAPTURE_ENABLED_CONFIG_SECTION, this._captureEnabled, vscode.ConfigurationTarget.Global);
|
||||
}
|
||||
}
|
||||
@@ -4,3 +4,5 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/// <reference path='../../../../src/vs/vscode.d.ts'/>
|
||||
/// <reference path='../../../../src/sql/azdata.d.ts'/>
|
||||
/// <reference path='../../../../src/sql/azdata.proposed.d.ts'/>
|
||||
|
||||
13
extensions/query-history/src/utils.ts
Normal file
13
extensions/query-history/src/utils.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Removes all newlines from the given string, replacing them with spaces
|
||||
* @param str The original string
|
||||
* @returns The string with all newlines replaced by spaces
|
||||
*/
|
||||
export function removeNewLines(str: string): string {
|
||||
return str.replace(/\r\n/g, ' ').replace(/\n/g, ' ');
|
||||
}
|
||||
Reference in New Issue
Block a user