mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-02 09:35:40 -05:00
Query History feature (#6579)
* Initial commit * Fix up QueryEventType * Making query history visible in view and open query command (#6479) * Add QueryInfo to query event events * Pull actual query text/connection info for displaying * cons and expand (#6489) * Making query history visible in view and open query command * expand and icons * Failure icon enabled (#6491) * Making query history visible in view and open query command * expand and icons * failure icon enabled * Minor cleanup * Open query with connection and add run query (#6496) * Add initial query-history extension * Fix issues caused by master merge, cleanup and add query-history extension (#6567) * Open query with connection and add run query * Fix issues caused by latest master merges, cleanup and add query-history extension * Remove child nodes (#6568) * Open query with connection and add run query * Fix issues caused by latest master merges, cleanup and add query-history extension * Remove child node expansion * Layering movement and add delete action (#6574) * Open query with connection and add run query * Fix issues caused by latest master merges, cleanup and add query-history extension * Remove child node expansion * Some layering movement and add delete action * Move query tracking into service (#6578) * Open query with connection and add run query * Fix issues caused by latest master merges, cleanup and add query-history extension * Remove child node expansion * Some layering movement and add delete action * Move query history tracking into service * Add comment * Fix actions * Remove unnecessary type * cleanup * Remove unused section of README * Fix merge issues and address PR comments * Fix compile and tslint errors * Change startup function name
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import QueryRunner from 'sql/platform/query/common/queryRunner';
|
||||
import QueryRunner, { IQueryMessage } from 'sql/platform/query/common/queryRunner';
|
||||
import { DataService } from 'sql/workbench/parts/grid/common/dataService';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
@@ -31,9 +31,15 @@ export interface IQueryPlanInfo {
|
||||
planXml: string;
|
||||
}
|
||||
|
||||
export interface IQueryInfo {
|
||||
selection: ISelectionData[];
|
||||
messages: IQueryMessage[];
|
||||
}
|
||||
|
||||
export interface IQueryEvent {
|
||||
type: queryeditor.QueryEvent;
|
||||
type: queryeditor.QueryEventType;
|
||||
uri: string;
|
||||
queryInfo: IQueryInfo;
|
||||
params?: any;
|
||||
}
|
||||
|
||||
|
||||
@@ -283,7 +283,12 @@ export class QueryModelService implements IQueryModelService {
|
||||
// fire extensibility API event
|
||||
let event: IQueryEvent = {
|
||||
type: 'queryStop',
|
||||
uri: uri
|
||||
uri: uri,
|
||||
queryInfo:
|
||||
{
|
||||
selection: info.selection,
|
||||
messages: info.queryRunner.messages
|
||||
}
|
||||
};
|
||||
this._onQueryEvent.fire(event);
|
||||
|
||||
@@ -296,7 +301,12 @@ export class QueryModelService implements IQueryModelService {
|
||||
// fire extensibility API event
|
||||
let event: IQueryEvent = {
|
||||
type: 'queryStart',
|
||||
uri: uri
|
||||
uri: uri,
|
||||
queryInfo:
|
||||
{
|
||||
selection: info.selection,
|
||||
messages: info.queryRunner.messages
|
||||
}
|
||||
};
|
||||
this._onQueryEvent.fire(event);
|
||||
|
||||
@@ -307,7 +317,12 @@ export class QueryModelService implements IQueryModelService {
|
||||
|
||||
let event: IQueryEvent = {
|
||||
type: 'queryUpdate',
|
||||
uri: uri
|
||||
uri: uri,
|
||||
queryInfo:
|
||||
{
|
||||
selection: info.selection,
|
||||
messages: info.queryRunner.messages
|
||||
}
|
||||
};
|
||||
this._onQueryEvent.fire(event);
|
||||
|
||||
@@ -319,6 +334,11 @@ export class QueryModelService implements IQueryModelService {
|
||||
let event: IQueryEvent = {
|
||||
type: 'executionPlan',
|
||||
uri: planInfo.fileUri,
|
||||
queryInfo:
|
||||
{
|
||||
selection: info.selection,
|
||||
messages: info.queryRunner.messages
|
||||
},
|
||||
params: planInfo
|
||||
};
|
||||
this._onQueryEvent.fire(event);
|
||||
@@ -328,6 +348,11 @@ export class QueryModelService implements IQueryModelService {
|
||||
let event: IQueryEvent = {
|
||||
type: 'visualize',
|
||||
uri: uri,
|
||||
queryInfo:
|
||||
{
|
||||
selection: info.selection,
|
||||
messages: info.queryRunner.messages
|
||||
},
|
||||
params: resultSetInfo
|
||||
};
|
||||
this._onQueryEvent.fire(event);
|
||||
@@ -443,7 +468,12 @@ export class QueryModelService implements IQueryModelService {
|
||||
// fire extensibility API event
|
||||
let event: IQueryEvent = {
|
||||
type: 'queryStop',
|
||||
uri: ownerUri
|
||||
uri: ownerUri,
|
||||
queryInfo:
|
||||
{
|
||||
selection: info.selection,
|
||||
messages: info.queryRunner.messages
|
||||
},
|
||||
};
|
||||
this._onQueryEvent.fire(event);
|
||||
|
||||
@@ -455,7 +485,12 @@ export class QueryModelService implements IQueryModelService {
|
||||
// fire extensibility API event
|
||||
let event: IQueryEvent = {
|
||||
type: 'queryStart',
|
||||
uri: ownerUri
|
||||
uri: ownerUri,
|
||||
queryInfo:
|
||||
{
|
||||
selection: info.selection,
|
||||
messages: info.queryRunner.messages
|
||||
},
|
||||
};
|
||||
this._onQueryEvent.fire(event);
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ export interface IQueryMessage extends azdata.IResultMessage {
|
||||
export default class QueryRunner extends Disposable {
|
||||
// MEMBER VARIABLES ////////////////////////////////////////////////////
|
||||
private _resultLineOffset: number;
|
||||
private _resultColumnOffset: number;
|
||||
private _totalElapsedMilliseconds: number = 0;
|
||||
private _isExecuting: boolean = false;
|
||||
private _hasCompleted: boolean = false;
|
||||
@@ -179,6 +180,7 @@ export default class QueryRunner extends Disposable {
|
||||
if (types.isObject(input) || types.isUndefinedOrNull(input)) {
|
||||
// Update internal state to show that we're executing the query
|
||||
this._resultLineOffset = input ? input.startLine : 0;
|
||||
this._resultColumnOffset = input ? input.startColumn : 0;
|
||||
this._isExecuting = true;
|
||||
this._totalElapsedMilliseconds = 0;
|
||||
// TODO issue #228 add statusview callbacks here
|
||||
@@ -243,8 +245,10 @@ export default class QueryRunner extends Disposable {
|
||||
|
||||
this._batchSets.map(batch => {
|
||||
if (batch.selection) {
|
||||
batch.selection.startLine = batch.selection.startLine + this._resultLineOffset;
|
||||
batch.selection.endLine = batch.selection.endLine + this._resultLineOffset;
|
||||
batch.selection.startLine += this._resultLineOffset;
|
||||
batch.selection.startColumn += this._resultColumnOffset;
|
||||
batch.selection.endLine += this._resultLineOffset;
|
||||
batch.selection.endColumn += this._resultColumnOffset;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -271,7 +275,9 @@ export default class QueryRunner extends Disposable {
|
||||
// Recalculate the start and end lines, relative to the result line offset
|
||||
if (batch.selection) {
|
||||
batch.selection.startLine += this._resultLineOffset;
|
||||
batch.selection.startColumn += this._resultColumnOffset;
|
||||
batch.selection.endLine += this._resultLineOffset;
|
||||
batch.selection.endColumn += this._resultColumnOffset;
|
||||
}
|
||||
|
||||
// Set the result sets as an empty array so that as result sets complete we can add to the list
|
||||
|
||||
34
src/sql/platform/queryHistory/common/queryHistoryInfo.ts
Normal file
34
src/sql/platform/queryHistory/common/queryHistoryInfo.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
|
||||
|
||||
export enum QueryStatus {
|
||||
Succeeded = 0,
|
||||
Failed = 1,
|
||||
Nothing = 2
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains information about a query that was ran
|
||||
*/
|
||||
export class QueryHistoryInfo {
|
||||
|
||||
public database: string;
|
||||
|
||||
public status: QueryStatus;
|
||||
|
||||
public readonly id = generateUuid();
|
||||
|
||||
constructor(
|
||||
public queryText: string,
|
||||
public connectionProfile: IConnectionProfile,
|
||||
public startTime: Date,
|
||||
status?: QueryStatus) {
|
||||
this.database = connectionProfile ? connectionProfile.databaseName : '';
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
25
src/sql/platform/queryHistory/common/queryHistoryService.ts
Normal file
25
src/sql/platform/queryHistory/common/queryHistoryService.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { QueryHistoryInfo } from 'sql/platform/queryHistory/common/queryHistoryInfo';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
|
||||
export const SERVICE_ID = 'queryHistoryService';
|
||||
|
||||
export const IQueryHistoryService = createDecorator<IQueryHistoryService>(SERVICE_ID);
|
||||
|
||||
/**
|
||||
* Service that collects the results of executed queries
|
||||
*/
|
||||
export interface IQueryHistoryService {
|
||||
_serviceBrand: any;
|
||||
|
||||
onInfosUpdated: Event<QueryHistoryInfo[]>;
|
||||
|
||||
getQueryHistoryInfos(): QueryHistoryInfo[];
|
||||
deleteQueryHistoryInfo(info: QueryHistoryInfo): void;
|
||||
start(): void;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IQueryHistoryService } from 'sql/platform/queryHistory/common/queryHistoryService.ts';
|
||||
|
||||
import { IQueryModelService, IQueryEvent } from 'sql/platform/query/common/queryModel';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { QueryHistoryInfo, QueryStatus } from 'sql/platform/queryHistory/common/queryHistoryInfo';
|
||||
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
/**
|
||||
* Service that collects the results of executed queries
|
||||
*/
|
||||
export class QueryHistoryService extends Disposable implements IQueryHistoryService {
|
||||
_serviceBrand: any;
|
||||
|
||||
// MEMBER VARIABLES ////////////////////////////////////////////////////
|
||||
private _infos: QueryHistoryInfo[] = [];
|
||||
private _onInfosUpdated: Emitter<QueryHistoryInfo[]> = new Emitter<QueryHistoryInfo[]>();
|
||||
|
||||
// EVENTS //////////////////////////////////////////////////////////////
|
||||
public get onInfosUpdated(): Event<QueryHistoryInfo[]> { return this._onInfosUpdated.event; }
|
||||
|
||||
// CONSTRUCTOR /////////////////////////////////////////////////////////
|
||||
constructor(
|
||||
@IQueryModelService _queryModelService: IQueryModelService,
|
||||
@IModelService _modelService: IModelService,
|
||||
@IConnectionManagementService _connectionManagementService: IConnectionManagementService
|
||||
) {
|
||||
super();
|
||||
|
||||
this._register(_queryModelService.onQueryEvent((e: IQueryEvent) => {
|
||||
if (e.type === 'queryStop') {
|
||||
const uri: URI = URI.parse(e.uri);
|
||||
// VS Range is 1 based so offset values by 1. The endLine we get back from SqlToolsService is incremented
|
||||
// by 1 from the original input range sent in as well so take that into account and don't modify
|
||||
const text: string = _modelService.getModel(uri).getValueInRange(new Range(
|
||||
e.queryInfo.selection[0].startLine + 1,
|
||||
e.queryInfo.selection[0].startColumn + 1,
|
||||
e.queryInfo.selection[0].endLine,
|
||||
e.queryInfo.selection[0].endColumn + 1));
|
||||
|
||||
const newInfo = new QueryHistoryInfo(text, _connectionManagementService.getConnectionProfile(e.uri), new Date(), QueryStatus.Succeeded);
|
||||
|
||||
// icon as required (for now logic is if any message has error query has error)
|
||||
let error: boolean = false;
|
||||
e.queryInfo.messages.forEach(x => error = error || x.isError);
|
||||
if (error) {
|
||||
newInfo.status = QueryStatus.Failed;
|
||||
}
|
||||
|
||||
// Append new node to beginning of array so the newest ones are at the top
|
||||
this._infos.unshift(newInfo);
|
||||
this._onInfosUpdated.fire(this._infos);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the current query history infos
|
||||
*/
|
||||
public getQueryHistoryInfos(): QueryHistoryInfo[] {
|
||||
return this._infos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes infos from the cache with the same ID as the given QueryHistoryInfo
|
||||
* @param info TheQueryHistoryInfo to delete
|
||||
*/
|
||||
public deleteQueryHistoryInfo(info: QueryHistoryInfo) {
|
||||
this._infos = this._infos.filter(i => i.id !== info.id);
|
||||
this._onInfosUpdated.fire(this._infos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to force initialization of the service so that it can start tracking query events
|
||||
*/
|
||||
public start(): void {
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user