mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-06 01:25:38 -05:00
Adds functionality to open execution plans from DB tables and DMVs. (#20377)
* Adds functionality to open execution plans from DB tables and DMVs. * Code review changes * Renames method to getProviderFromUri
This commit is contained in:
@@ -70,7 +70,12 @@ export class ExecutionPlanEditorOverrideContribution extends Disposable implemen
|
||||
},
|
||||
{},
|
||||
(editorInput, group) => {
|
||||
const executionPlanInput = this._instantiationService.createInstance(ExecutionPlanInput, editorInput.resource);
|
||||
const executionPlanGraphInfo = {
|
||||
graphFileContent: undefined,
|
||||
graphFileType: undefined
|
||||
};
|
||||
|
||||
const executionPlanInput = this._instantiationService.createInstance(ExecutionPlanInput, editorInput.resource, executionPlanGraphInfo);
|
||||
return { editor: executionPlanInput, options: editorInput.options, group: group };
|
||||
}
|
||||
);
|
||||
|
||||
@@ -5,23 +5,41 @@
|
||||
|
||||
import * as path from 'vs/base/common/path';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { localize } from 'vs/nls';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
import { EditorModel } from 'vs/workbench/common/editor/editorModel';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import * as azdata from 'azdata';
|
||||
|
||||
export class ExecutionPlanInput extends EditorInput {
|
||||
|
||||
public static ID: string = 'workbench.editorinputs.executionplan';
|
||||
public static SCHEMA: string = 'executionplan';
|
||||
private readonly editorNamePrefix = localize('epCompare.executionPlanEditorName', 'ExecutionPlan');
|
||||
private _editorName: string;
|
||||
|
||||
private _content?: string;
|
||||
public _executionPlanFileViewUUID: string;
|
||||
|
||||
constructor(
|
||||
private _uri: URI,
|
||||
private _uri: URI | undefined,
|
||||
private executionPlanGraphinfo: azdata.executionPlan.ExecutionPlanGraphInfo,
|
||||
@ITextFileService private readonly _fileService: ITextFileService,
|
||||
@IEditorService private readonly _editorService: IEditorService
|
||||
) {
|
||||
super();
|
||||
|
||||
if (this._uri === undefined && !!this.executionPlanGraphinfo.graphFileContent && !!this.executionPlanGraphinfo.graphFileType) {
|
||||
const existingNames = this._editorService.editors.map(editor => editor.getName());
|
||||
let i = 0;
|
||||
this._editorName = `${this.editorNamePrefix}${i}.${this.executionPlanGraphinfo.graphFileType}`;
|
||||
while (existingNames.includes(this._editorName)) {
|
||||
i++;
|
||||
this._editorName = `${this.editorNamePrefix}${i}.${this.executionPlanGraphinfo.graphFileType}`;
|
||||
}
|
||||
|
||||
this._uri = URI.parse(this._editorName);
|
||||
}
|
||||
}
|
||||
|
||||
public get executionPlanFileViewUUID(): string {
|
||||
@@ -37,14 +55,18 @@ export class ExecutionPlanInput extends EditorInput {
|
||||
}
|
||||
|
||||
public override getName(): string {
|
||||
if (this._editorName) {
|
||||
return this._editorName;
|
||||
}
|
||||
|
||||
return path.basename(this._uri.fsPath);
|
||||
}
|
||||
|
||||
public async content(): Promise<string> {
|
||||
if (!this._content) {
|
||||
this._content = (await this._fileService.read(this._uri, { acceptTextOnly: true })).value;
|
||||
if (!this.executionPlanGraphinfo.graphFileContent) {
|
||||
this.executionPlanGraphinfo.graphFileContent = (await this._fileService.read(this._uri, { acceptTextOnly: true })).value;
|
||||
}
|
||||
return this._content;
|
||||
return this.executionPlanGraphinfo.graphFileContent;
|
||||
}
|
||||
|
||||
public getUri(): string {
|
||||
@@ -60,8 +82,8 @@ export class ExecutionPlanInput extends EditorInput {
|
||||
}
|
||||
|
||||
public override async resolve(refresh?: boolean): Promise<EditorModel | undefined> {
|
||||
if (!this._content) {
|
||||
this._content = (await this._fileService.read(this._uri, { acceptTextOnly: true })).value;
|
||||
if (!this.executionPlanGraphinfo.graphFileContent) {
|
||||
this.executionPlanGraphinfo.graphFileContent = (await this._fileService.read(this._uri, { acceptTextOnly: true })).value;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { getChartMaxRowCount, notifyMaxRowCountExceeded } from 'sql/workbench/contrib/charts/browser/utils';
|
||||
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
|
||||
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
|
||||
import { IExecutionPlanService } from 'sql/workbench/services/executionPlan/common/interfaces';
|
||||
|
||||
@Component({
|
||||
selector: GridOutputComponent.SELECTOR,
|
||||
@@ -237,12 +238,13 @@ class DataResourceTable extends GridTableBase<any> {
|
||||
@IQueryModelService queryModelService: IQueryModelService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IContextViewService contextViewService: IContextViewService,
|
||||
@INotificationService notificationService: INotificationService
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@IExecutionPlanService executionPlanService: IExecutionPlanService
|
||||
) {
|
||||
super(state, createResultSet(source), {
|
||||
actionOrientation: ActionsOrientation.HORIZONTAL,
|
||||
inMemoryDataProcessing: true
|
||||
}, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService);
|
||||
}, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService, executionPlanService);
|
||||
this._gridDataProvider = this.instantiationService.createInstance(DataResourceDataProvider, source, this.resultSet, this.cellModel);
|
||||
this._chart = this.instantiationService.createInstance(ChartView, false);
|
||||
|
||||
|
||||
@@ -52,6 +52,8 @@ import { HybridDataProvider } from 'sql/base/browser/ui/table/hybridDataProvider
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { alert, status } from 'vs/base/browser/ui/aria/aria';
|
||||
import { CopyAction } from 'vs/editor/contrib/clipboard/clipboard';
|
||||
import { IExecutionPlanService } from 'sql/workbench/services/executionPlan/common/interfaces';
|
||||
import { ExecutionPlanInput } from 'sql/workbench/contrib/executionPlan/common/executionPlanInput';
|
||||
|
||||
const ROW_HEIGHT = 29;
|
||||
const HEADER_HEIGHT = 26;
|
||||
@@ -375,6 +377,8 @@ export abstract class GridTableBase<T> extends Disposable implements IView {
|
||||
|
||||
public isOnlyTable: boolean = true;
|
||||
|
||||
public providerId: string;
|
||||
|
||||
// this handles if the row count is small, like 4-5 rows
|
||||
protected get maxSize(): number {
|
||||
return ((this.resultSet.rowCount) * this.rowHeight) + HEADER_HEIGHT + ESTIMATED_SCROLL_BAR_HEIGHT;
|
||||
@@ -400,7 +404,8 @@ export abstract class GridTableBase<T> extends Disposable implements IView {
|
||||
@IQueryModelService private readonly queryModelService: IQueryModelService,
|
||||
@IThemeService private readonly themeService: IThemeService,
|
||||
@IContextViewService private readonly contextViewService: IContextViewService,
|
||||
@INotificationService private readonly notificationService: INotificationService
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IExecutionPlanService private readonly executionPlanService: IExecutionPlanService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -712,12 +717,24 @@ export abstract class GridTableBase<T> extends Disposable implements IView {
|
||||
const value = subset[0][event.cell.cell - 1];
|
||||
const isJson = isJsonCell(value);
|
||||
if (column.isXml || isJson) {
|
||||
const content = value.displayValue;
|
||||
const input = this.untitledEditorService.create({ mode: column.isXml ? 'xml' : 'json', initialValue: content });
|
||||
await input.resolve();
|
||||
await this.instantiationService.invokeFunction(formatDocumentWithSelectedProvider, input.textEditorModel, FormattingMode.Explicit, Progress.None, CancellationToken.None);
|
||||
input.setDirty(false);
|
||||
await this.editorService.openEditor(input);
|
||||
const result = await this.executionPlanService.isExecutionPlan(this.providerId, value.displayValue);
|
||||
if (result.isExecutionPlan) {
|
||||
const executionPlanGraphInfo = {
|
||||
graphFileContent: value.displayValue,
|
||||
graphFileType: result.queryExecutionPlanFileExtension
|
||||
};
|
||||
|
||||
const executionPlanInput = this.instantiationService.createInstance(ExecutionPlanInput, undefined, executionPlanGraphInfo);
|
||||
await this.editorService.openEditor(executionPlanInput);
|
||||
}
|
||||
else {
|
||||
const content = value.displayValue;
|
||||
const input = this.untitledEditorService.create({ mode: column.isXml ? 'xml' : 'json', initialValue: content });
|
||||
await input.resolve();
|
||||
await this.instantiationService.invokeFunction(formatDocumentWithSelectedProvider, input.textEditorModel, FormattingMode.Explicit, Progress.None, CancellationToken.None);
|
||||
input.setDirty(false);
|
||||
await this.editorService.openEditor(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -901,15 +918,17 @@ class GridTable<T> extends GridTableBase<T> {
|
||||
@IQueryModelService queryModelService: IQueryModelService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IContextViewService contextViewService: IContextViewService,
|
||||
@INotificationService notificationService: INotificationService
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@IExecutionPlanService executionPlanService: IExecutionPlanService
|
||||
) {
|
||||
super(state, resultSet, {
|
||||
actionOrientation: ActionsOrientation.VERTICAL,
|
||||
inMemoryDataProcessing: true,
|
||||
showActionBar: true,
|
||||
inMemoryDataCountThreshold: configurationService.getValue<IQueryEditorConfiguration>('queryEditor').results.inMemoryDataProcessingThreshold,
|
||||
}, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService);
|
||||
}, contextMenuService, instantiationService, editorService, untitledEditorService, configurationService, queryModelService, themeService, contextViewService, notificationService, executionPlanService);
|
||||
this._gridDataProvider = this.instantiationService.createInstance(QueryGridDataProvider, this._runner, resultSet.batchId, resultSet.id);
|
||||
this.providerId = this._runner.getProviderId();
|
||||
}
|
||||
|
||||
get gridDataProvider(): IGridDataProvider {
|
||||
|
||||
Reference in New Issue
Block a user