Pushing initial work for done in Query plan feature to main (#17986)
* Adding initial boilerplate for qp2 * Adding feature flag in query plan 2 * Clearing show plan 2 after every run * Adding sub tree cost * removing unused method. * WIP 2 * Adding properties view and relative cost to query plan * WIP * Add icons to ads * Assing relative costs and prop windows * Enabling older query plan again * Making some PR fixes * Some more PR related fixes * Use MS org azdataGraph module * Moving new properties to azdata proposed. * Moving new class properties to proposed * added missing doc component. * Changing how azdatagraph package is referenced * Removing empty lines, fixing localization keys * Removing empty line, localizing some string * making css classes more specific * making some logic concise * localizing some more strings * Making more css classes specific * Removing important tag from css props * Checking if sum is greater than 0 to prevent divide by zero exceptions * Fixed loader error in bootstrap * Fixing query index * -fixing image paths -making css class more class specific by using nested selectors Co-authored-by: kburtram <karlb@microsoft.com>
@@ -761,7 +761,8 @@
|
||||
"vscode-textmate",
|
||||
"vscode-oniguruma",
|
||||
"iconv-lite-umd",
|
||||
"jschardet"
|
||||
"jschardet",
|
||||
"azdataGraph"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -120,7 +120,8 @@
|
||||
"xterm-headless": "4.14.0-beta.11",
|
||||
"yauzl": "^2.9.2",
|
||||
"yazl": "^2.4.3",
|
||||
"zone.js": "^0.8.4"
|
||||
"zone.js": "^0.8.4",
|
||||
"azdataGraph": "github:Microsoft/azdataGraph#0.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"7zip": "0.0.6",
|
||||
|
||||
5
src/bootstrap-window.js
vendored
@@ -141,7 +141,8 @@
|
||||
'jschardet': `${baseNodeModulesPath}/jschardet/dist/jschardet.min.js`,
|
||||
'@vscode/vscode-languagedetection': `${baseNodeModulesPath}/@vscode/vscode-languagedetection/dist/lib/index.js`,
|
||||
'tas-client-umd': `${baseNodeModulesPath}/tas-client-umd/lib/tas-client-umd.js`,
|
||||
'ansi_up': `${baseNodeModulesPath}/ansi_up/ansi_up.js`
|
||||
'ansi_up': `${baseNodeModulesPath}/ansi_up/ansi_up.js`,
|
||||
'azdataGraph': `${baseNodeModulesPath}/azdataGraph/dist/build.js`
|
||||
};
|
||||
|
||||
// For priviledged renderers, allow to load built-in and other node.js
|
||||
@@ -153,7 +154,7 @@
|
||||
// the expected method and so nothing needs to be done - but if it's AMD then the VS Code loader will throw an error
|
||||
// (Can only have one anonymous define call per script file). In order to make packages that do this load correctly
|
||||
// we need to add them to the list below to tell the loader that these should be loaded using AMD as well
|
||||
loaderConfig.amdModulesPattern = /(vs|sql)\/|(^vscode-textmate$)|(^vscode-oniguruma$)|(^xterm$)|(^xterm-addon-search$)|(^xterm-addon-unicode11$)|(^xterm-addon-webgl$)|(^iconv-lite-umd$)|(^jschardet$)|(^@vscode\/vscode-languagedetection$)|(^tas-client-umd$)|(^ansi_up$)/; // {{SQL CARBON EDIT}} include sql and ansi_up in regex
|
||||
loaderConfig.amdModulesPattern = /(vs|sql)\/|(^vscode-textmate$)|(^vscode-oniguruma$)|(^xterm$)|(^xterm-addon-search$)|(^xterm-addon-unicode11$)|(^xterm-addon-webgl$)|(^iconv-lite-umd$)|(^jschardet$)|(^@vscode\/vscode-languagedetection$)|(^tas-client-umd$)|(^ansi_up$)|(^azdataGraph$)/; // {{SQL CARBON EDIT}} include sql and ansi_up in regex
|
||||
}
|
||||
|
||||
// Signal before require.config()
|
||||
|
||||
107
src/sql/azdata.proposed.d.ts
vendored
@@ -913,11 +913,22 @@ declare module 'azdata' {
|
||||
action: ActionOnCellCheckboxCheck;
|
||||
}
|
||||
|
||||
export interface QueryExecuteResultSetNotificationParams {
|
||||
/**
|
||||
* Contains query plans returned by the database in ResultSets.
|
||||
*/
|
||||
executionPlans: QueryPlanGraph[];
|
||||
}
|
||||
|
||||
export interface ResultSetSummary {
|
||||
/**
|
||||
* The visualization options for the result set.
|
||||
*/
|
||||
visualization?: VisualizationOptions;
|
||||
/**
|
||||
* Generic query plan graph to be displayed in the results view.
|
||||
*/
|
||||
showplangraph?: QueryPlanGraph;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1392,4 +1403,100 @@ declare module 'azdata' {
|
||||
errors?: { message: string, property?: DesignerEditPath }[];
|
||||
}
|
||||
}
|
||||
|
||||
export interface QueryPlanGraph {
|
||||
/**
|
||||
* Root of the query plan tree
|
||||
*/
|
||||
root: QueryPlanGraphNode;
|
||||
/**
|
||||
* Underlying query for the query plan graph.
|
||||
*/
|
||||
query: string;
|
||||
}
|
||||
|
||||
export interface QueryPlanGraphNode {
|
||||
/**
|
||||
* Type of the node. This property determines the icon that is displayed for it
|
||||
*/
|
||||
type: string;
|
||||
/**
|
||||
* Cost associated with the node
|
||||
*/
|
||||
cost: number;
|
||||
/**
|
||||
* Cost of the node subtree
|
||||
*/
|
||||
subTreeCost: number;
|
||||
/**
|
||||
* Relative cost of the node compared to its siblings.
|
||||
*/
|
||||
relativeCost: number;
|
||||
/**
|
||||
* Time take by the node operation in milliseconds
|
||||
*/
|
||||
elapsedTimeInMs: number;
|
||||
/**
|
||||
* Node properties to be shown in the tooltip
|
||||
*/
|
||||
properties: QueryPlanGraphElementProperty[];
|
||||
/**
|
||||
* Display name for the node
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Description associated with the node.
|
||||
*/
|
||||
description: string;
|
||||
/**
|
||||
* Subtext displayed under the node name
|
||||
*/
|
||||
subtext: string[];
|
||||
/**
|
||||
* Direct children of the nodes.
|
||||
*/
|
||||
children: QueryPlanGraphNode[];
|
||||
/**
|
||||
* Edges corresponding to the children.
|
||||
*/
|
||||
edges: QueryGraphEdge[];
|
||||
}
|
||||
|
||||
export interface QueryGraphEdge {
|
||||
/**
|
||||
* Count of the rows returned by the subtree of the edge.
|
||||
*/
|
||||
rowCount: number;
|
||||
/**
|
||||
* Size of the rows returned by the subtree of the edge.
|
||||
*/
|
||||
rowSize: number;
|
||||
/**
|
||||
* Edge properties to be shown in the tooltip.
|
||||
*/
|
||||
properties: QueryPlanGraphElementProperty[]
|
||||
}
|
||||
|
||||
export interface QueryPlanGraphElementProperty {
|
||||
/**
|
||||
* Name of the property
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Formatted value for the property
|
||||
*/
|
||||
formattedValue: string;
|
||||
/**
|
||||
* Flag to show/hide props in tooltip
|
||||
*/
|
||||
showInToolTip: boolean;
|
||||
/**
|
||||
* Display order of property
|
||||
*/
|
||||
displayOrder: number;
|
||||
/**
|
||||
* Flag to indicate if the property has a longer value so that it will be shown at the bottom of the tooltip
|
||||
*/
|
||||
isLongString: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { attachTabbedPanelStyler } from 'sql/workbench/common/styler';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { QueryPlan2Tab } from 'sql/workbench/contrib/queryplan2/browser/queryPlan';
|
||||
|
||||
class MessagesView extends Disposable implements IPanelView {
|
||||
private messagePanel: MessagePanel;
|
||||
@@ -163,6 +164,7 @@ export class QueryResultsView extends Disposable {
|
||||
private messagesTab: MessagesTab;
|
||||
private chartTab: ChartTab;
|
||||
private qpTab: QueryPlanTab;
|
||||
private qp2Tab: QueryPlan2Tab;
|
||||
private topOperationsTab: TopOperationsTab;
|
||||
private dynamicModelViewTabs: QueryModelViewTab[] = [];
|
||||
|
||||
@@ -183,6 +185,7 @@ export class QueryResultsView extends Disposable {
|
||||
this._panelView = this._register(new TabbedPanel(container, { showHeaderWhenSingleView: true }));
|
||||
this._register(attachTabbedPanelStyler(this._panelView, themeService));
|
||||
this.qpTab = this._register(new QueryPlanTab());
|
||||
this.qp2Tab = this._register(new QueryPlan2Tab());
|
||||
this.topOperationsTab = this._register(new TopOperationsTab(instantiationService));
|
||||
|
||||
this._panelView.pushTab(this.resultsTab);
|
||||
@@ -223,6 +226,7 @@ export class QueryResultsView extends Disposable {
|
||||
this.hideResults();
|
||||
this.hideChart();
|
||||
this.hidePlan();
|
||||
this.hidePlan2();
|
||||
this.hideDynamicViewModelTabs();
|
||||
this.input?.state.visibleTabs.clear();
|
||||
if (this.input) {
|
||||
@@ -245,6 +249,15 @@ export class QueryResultsView extends Disposable {
|
||||
}
|
||||
}));
|
||||
|
||||
this.runnerDisposables.add(runner.onQueryPlan2Available(e => {
|
||||
if (this.qp2Tab) {
|
||||
if (!this.input.state.visibleTabs.has(this.qp2Tab.identifier)) {
|
||||
this.showPlan2();
|
||||
}
|
||||
this.qp2Tab.view.addGraphs(e.planGraphs);
|
||||
}
|
||||
}));
|
||||
|
||||
if (this.input?.state.visibleTabs.has(this.chartTab.identifier) && !this._panelView.contains(this.chartTab)) {
|
||||
this._panelView.pushTab(this.chartTab);
|
||||
} else if (!this.input?.state.visibleTabs.has(this.chartTab.identifier) && this._panelView.contains(this.chartTab)) {
|
||||
@@ -257,6 +270,12 @@ export class QueryResultsView extends Disposable {
|
||||
this._panelView.removeTab(this.qpTab.identifier);
|
||||
}
|
||||
|
||||
if (this.input?.state.visibleTabs.has(this.qp2Tab.identifier) && !this._panelView.contains(this.qp2Tab)) {
|
||||
this._panelView.pushTab(this.qp2Tab);
|
||||
} else if (!this.input?.state.visibleTabs.has(this.qp2Tab.identifier) && this._panelView.contains(this.qp2Tab)) {
|
||||
this._panelView.removeTab(this.qp2Tab.identifier);
|
||||
}
|
||||
|
||||
if (this.input?.state.visibleTabs.has(this.topOperationsTab.identifier) && !this._panelView.contains(this.topOperationsTab)) {
|
||||
this._panelView.pushTab(this.topOperationsTab);
|
||||
} else if (!this.input?.state.visibleTabs.has(this.topOperationsTab.identifier) && this._panelView.contains(this.topOperationsTab)) {
|
||||
@@ -309,7 +328,7 @@ export class QueryResultsView extends Disposable {
|
||||
this._input = input;
|
||||
this.runnerDisposables.clear();
|
||||
|
||||
[this.resultsTab, this.messagesTab, this.qpTab, this.topOperationsTab, this.chartTab].forEach(t => t.clear());
|
||||
[this.resultsTab, this.messagesTab, this.qpTab, this.qp2Tab, this.topOperationsTab, this.chartTab].forEach(t => t.clear());
|
||||
this.dynamicModelViewTabs.forEach(t => t.clear());
|
||||
|
||||
if (input) {
|
||||
@@ -412,6 +431,16 @@ export class QueryResultsView extends Disposable {
|
||||
this.topOperationsTab.view.showPlan(xml);
|
||||
}
|
||||
|
||||
public showPlan2() {
|
||||
if (!this._panelView.contains(this.qp2Tab)) {
|
||||
this.input?.state.visibleTabs.add(this.qp2Tab.identifier);
|
||||
if (!this._panelView.contains(this.qp2Tab)) {
|
||||
this._panelView.pushTab(this.qp2Tab);
|
||||
}
|
||||
this._panelView.showTab(this.qp2Tab.identifier);
|
||||
}
|
||||
}
|
||||
|
||||
public hidePlan() {
|
||||
if (this._panelView.contains(this.qpTab)) {
|
||||
this._panelView.removeTab(this.qpTab.identifier);
|
||||
@@ -422,6 +451,13 @@ export class QueryResultsView extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
public hidePlan2() {
|
||||
if (this._panelView.contains(this.qp2Tab)) {
|
||||
this.qp2Tab.clear();
|
||||
this._panelView.removeTab(this.qp2Tab.identifier);
|
||||
}
|
||||
}
|
||||
|
||||
public hideDynamicViewModelTabs() {
|
||||
this.dynamicModelViewTabs.forEach(tab => {
|
||||
if (this._panelView.contains(tab)) {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { QueryPlan2 } from 'sql/workbench/contrib/queryplan2/browser/queryPlan';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
|
||||
export class PropertiesAction extends Action {
|
||||
public static ID = 'qp.propertiesAction';
|
||||
public static LABEL = localize('queryPlanPropertiesActionLabel', "Properties");
|
||||
|
||||
constructor() {
|
||||
super(PropertiesAction.ID, PropertiesAction.LABEL, Codicon.listUnordered.classNames);
|
||||
}
|
||||
|
||||
public override async run(context: QueryPlan2): Promise<void> {
|
||||
context.propContainer.style.visibility = context.propContainer.style.visibility === 'visible' ? 'hidden' : 'visible';
|
||||
}
|
||||
}
|
||||
BIN
src/sql/workbench/contrib/queryplan2/browser/images/collapse.gif
Normal file
|
After Width: | Height: | Size: 846 B |
BIN
src/sql/workbench/contrib/queryplan2/browser/images/expand.gif
Normal file
|
After Width: | Height: | Size: 851 B |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 867 B |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 908 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 980 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/sql/workbench/contrib/queryplan2/browser/images/icons/if.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 966 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 843 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 783 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 908 B |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 897 B |
|
After Width: | Height: | Size: 995 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |