Readd query plan (#2409)

* fix grid links

* formatting

* remove commented code

* adding query plan

* asd

* add query plan

* fix title
This commit is contained in:
Anthony Dresser
2018-09-05 12:11:33 -07:00
committed by GitHub
parent ce0c955c29
commit 1356f0bcf6
7 changed files with 122 additions and 3 deletions

View File

@@ -106,4 +106,4 @@ export const textFormatter: Slick.Formatter<any> = (row, cell, value, columnDef,
return cellContainer.outerHTML;
};
*/
*/

View File

@@ -180,3 +180,25 @@ export class ChartDataAction extends Action {
}
}
}
export class ShowQueryPlanAction extends Action {
public static ID = 'showQueryPlan';
public static LABEL = localize('showQueryPlan', 'Show Query Plan');
constructor(
@IEditorService private editorService: IEditorService
) {
super(ShowQueryPlanAction.ID, ShowQueryPlanAction.LABEL);
}
public run(xml: string): TPromise<boolean> {
let activeEditor = this.editorService.activeControl;
if (activeEditor instanceof QueryEditor) {
activeEditor.resultsEditor.showQueryPlan(xml);
return TPromise.as(true);
} else {
return TPromise.as(false);
}
}
}

View File

@@ -12,7 +12,7 @@ import { ScrollableSplitView } from 'sql/base/browser/ui/scrollableSplitview/scr
import { MouseWheelSupport } from 'sql/base/browser/ui/table/plugins/mousewheelTableScroll.plugin';
import { AutoColumnSize } from 'sql/base/browser/ui/table/plugins/autoSizeColumns.plugin';
import { SaveFormat } from 'sql/parts/grid/common/interfaces';
import { IGridActionContext, SaveResultAction, CopyResultAction, SelectAllGridAction, MaximizeTableAction, MinimizeTableAction, ChartDataAction } from 'sql/parts/query/editor/actions';
import { IGridActionContext, SaveResultAction, CopyResultAction, SelectAllGridAction, MaximizeTableAction, MinimizeTableAction, ChartDataAction, ShowQueryPlanAction } from 'sql/parts/query/editor/actions';
import { CellSelectionModel } from 'sql/base/browser/ui/table/plugins/cellSelectionModel.plugin';
import { RowNumberColumn } from 'sql/base/browser/ui/table/plugins/rowNumberColumn.plugin';
import { escape } from 'sql/base/common/strings';
@@ -364,6 +364,9 @@ class GridTable<T> extends Disposable implements IView {
private loadData(offset: number, count: number): Thenable<T[]> {
return this.runner.getQueryRows(offset, count, this.resultSet.batchId, this.resultSet.id).then(response => {
if (this.runner.isQueryPlan) {
this.instantiationService.createInstance(ShowQueryPlanAction).run(response.resultSubset.rows[0][0].displayValue);
}
return response.resultSubset.rows.map(r => {
let dataWithSchema = {};
// skip the first column since its a number column

View File

@@ -152,6 +152,10 @@ export class QueryResultsEditor extends BaseEditor {
this.resultsView.chartData(dataId);
}
public showQueryPlan(xml: string) {
this.resultsView.showPlan(xml);
}
public dispose(): void {
super.dispose();
}

View File

@@ -10,13 +10,14 @@ import { IQueryModelService } from '../execution/queryModel';
import QueryRunner from 'sql/parts/query/execution/queryRunner';
import { MessagePanel } from './messagePanel';
import { GridPanel } from './gridPanel';
import { ChartTab } from './charting/chartTab';
import { QueryPlanTab } from 'sql/parts/queryPlan/queryPlan';
import * as nls from 'vs/nls';
import * as UUID from 'vs/base/common/uuid';
import { PanelViewlet } from 'vs/workbench/browser/parts/views/panelViewlet';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import * as DOM from 'vs/base/browser/dom';
import { ChartTab } from './charting/chartTab';
class ResultsView implements IPanelView {
private panelViewlet: PanelViewlet;
@@ -79,6 +80,7 @@ export class QueryResultsView {
private _input: QueryResultsInput;
private resultsTab: ResultsTab;
private chartTab: ChartTab;
private qpTab: QueryPlanTab;
constructor(
container: HTMLElement,
@@ -88,6 +90,7 @@ export class QueryResultsView {
this.resultsTab = new ResultsTab(instantiationService);
this.chartTab = new ChartTab(instantiationService);
this._panelView = new TabbedPanel(container, { showHeaderWhenSingleView: false });
this.qpTab = new QueryPlanTab();
}
public style() {
@@ -119,4 +122,13 @@ export class QueryResultsView {
this._panelView.showTab(this.chartTab.identifier);
this.chartTab.chart(dataId);
}
public showPlan(xml: string) {
if (!this._panelView.contains(this.qpTab)) {
this._panelView.pushTab(this.qpTab);
}
this._panelView.showTab(this.qpTab.identifier);
this.qpTab.view.showPlan(xml);
}
}

View File

@@ -63,6 +63,9 @@ export default class QueryRunner {
private _hasCompleted: boolean = false;
private _batchSets: sqlops.BatchSummary[] = [];
private _eventEmitter = new EventEmitter();
private _isQueryPlan: boolean;
public get isQueryPlan(): boolean { return this._isQueryPlan; }
private _onMessage = new Emitter<sqlops.IResultMessage>();
public readonly onMessage = debounceEvent<sqlops.IResultMessage, sqlops.IResultMessage[]>(echo(this._onMessage.event), (l, e) => {
@@ -171,6 +174,12 @@ export default class QueryRunner {
this._totalElapsedMilliseconds = 0;
// TODO issue #228 add statusview callbacks here
if (runOptions && (runOptions.displayActualQueryPlan || runOptions.displayEstimatedQueryPlan)) {
this._isQueryPlan = true;
} else {
this._isQueryPlan = false;
}
// Send the request to execute the query
return runCurrentStatement
? this._queryManagementService.runQueryStatement(ownerUri, input.startLine, input.startColumn).then(() => this.handleSuccessRunQueryResult(), e => this.handleFailureRunQueryResult(e))

View File

@@ -0,0 +1,69 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as QP from 'html-query-plan';
import { IPanelView, IPanelTab } from 'sql/base/browser/ui/panel/panel';
import { Dimension } from 'vs/base/browser/dom';
import { localize } from 'vs/nls';
import * as UUID from 'vs/base/common/uuid';
import { Builder } from 'vs/base/browser/builder';
export class QueryPlanTab implements IPanelTab {
public readonly title = localize('queryPlanTitle', 'Query Plan');
public readonly identifier = UUID.generateUuid();
public readonly view: QueryPlanView;
constructor() {
this.view = new QueryPlanView();
}
}
export class QueryPlanView implements IPanelView {
private qp: QueryPlan;
private xml: string;
private container = document.createElement('div');
public render(container: HTMLElement): void {
if (!this.qp) {
this.qp = new QueryPlan(this.container);
if (this.xml) {
this.qp.xml = this.xml;
}
}
container.appendChild(this.container);
}
public layout(dimension: Dimension): void {
}
public showPlan(xml: string) {
if (this.qp) {
this.qp.xml = xml;
} else {
this.xml = xml;
}
}
}
export class QueryPlan {
private _xml: string;
constructor(private container: HTMLElement) {
}
public set xml(xml: string) {
this._xml = xml;
new Builder(this.container).empty();
QP.showPlan(this.container, this._xml, {
jsTooltips: false
});
}
public get xml(): string {
return this._xml;
}
}