diff --git a/src/sql/azdata.proposed.d.ts b/src/sql/azdata.proposed.d.ts index bb4902e6e4..c2a4754c8c 100644 --- a/src/sql/azdata.proposed.d.ts +++ b/src/sql/azdata.proposed.d.ts @@ -1264,6 +1264,27 @@ declare module 'azdata' { * Edges corresponding to the children. */ edges: ExecutionPlanEdge[]; + /** + * Warning/parallelism badges applicable to the current node + */ + badges: ExecutionPlanBadge[]; + } + + export interface ExecutionPlanBadge { + /** + * Type of the node overlay. This determines the icon that is displayed for it + */ + type: BadgeType; + /** + * Text to display for the overlay tooltip + */ + tooltip: string; + } + + export enum BadgeType { + Warning = 0, + CriticalWarning = 1, + Parallelism = 2 } export interface ExecutionPlanEdge { diff --git a/src/sql/workbench/api/common/sqlExtHost.api.impl.ts b/src/sql/workbench/api/common/sqlExtHost.api.impl.ts index 2ec19cc4ac..28f112d36f 100644 --- a/src/sql/workbench/api/common/sqlExtHost.api.impl.ts +++ b/src/sql/workbench/api/common/sqlExtHost.api.impl.ts @@ -593,6 +593,10 @@ export function createAdsApiFactory(accessor: ServicesAccessor): IAdsExtensionAp } }; + const executionPlan: typeof azdata.executionPlan = { + BadgeType: sqlExtHostTypes.executionPlan.BadgeType + }; + return { version: initData.version, accounts, @@ -644,7 +648,8 @@ export function createAdsApiFactory(accessor: ServicesAccessor): IAdsExtensionAp TabOrientation: sqlExtHostTypes.TabOrientation, sqlAssessment, TextType: sqlExtHostTypes.TextType, - designers: designers + designers: designers, + executionPlan: executionPlan }; }, extHostNotebook: extHostNotebook, diff --git a/src/sql/workbench/api/common/sqlExtHostTypes.ts b/src/sql/workbench/api/common/sqlExtHostTypes.ts index b41ccdbbdc..4b3fe83601 100644 --- a/src/sql/workbench/api/common/sqlExtHostTypes.ts +++ b/src/sql/workbench/api/common/sqlExtHostTypes.ts @@ -1031,3 +1031,11 @@ export namespace designers { GraphNode = 'GraphNode' } } + +export namespace executionPlan { + export enum BadgeType { + Warning = 0, + CriticalWarning = 1, + Parallelism = 2 + } +} diff --git a/src/sql/workbench/contrib/executionPlan/browser/constants.ts b/src/sql/workbench/contrib/executionPlan/browser/constants.ts index e1845ed350..b1d0879a8d 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/constants.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/constants.ts @@ -249,6 +249,14 @@ export let executionPlanNodeIconPaths = unionAll: imageBasePath + 'union_all.png' }; +export const badgeIconPaths = { + warning: imageBasePath + 'badge_warning.svg', + + parallelism: imageBasePath + 'badge_parallelism.svg', + + criticalWarning: imageBasePath + 'badge_critical_warning.svg' +}; + const parentContainer = 'qps-container'; export const savePlanIconClassNames = [parentContainer, 'save-plan-icon'].join(' '); export const openPropertiesIconClassNames = [parentContainer, 'open-properties-icon'].join(' '); diff --git a/src/sql/workbench/contrib/executionPlan/browser/executionPlan.ts b/src/sql/workbench/contrib/executionPlan/browser/executionPlan.ts index 75356b1e87..3c77278aa2 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlan.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlan.ts @@ -4,14 +4,15 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/executionPlan'; -import type * as azdata from 'azdata'; +import * as azdata from 'azdata'; +import * as sqlExtHostType from 'sql/workbench/api/common/sqlExtHostTypes'; import { IPanelView, IPanelTab } from 'sql/base/browser/ui/panel/panel'; import { localize } from 'vs/nls'; import { dispose } from 'vs/base/common/lifecycle'; import { ActionBar } from 'sql/base/browser/ui/taskbar/actionbar'; import * as DOM from 'vs/base/browser/dom'; import * as azdataGraphModule from 'azdataGraph'; -import { customZoomIconClassNames, openPlanFileIconClassNames, openPropertiesIconClassNames, openQueryIconClassNames, executionPlanNodeIconPaths, savePlanIconClassNames, searchIconClassNames, zoomInIconClassNames, zoomOutIconClassNames, zoomToFitIconClassNames } from 'sql/workbench/contrib/executionPlan/browser/constants'; +import { customZoomIconClassNames, openPlanFileIconClassNames, openPropertiesIconClassNames, openQueryIconClassNames, executionPlanNodeIconPaths, savePlanIconClassNames, searchIconClassNames, zoomInIconClassNames, zoomOutIconClassNames, zoomToFitIconClassNames, badgeIconPaths } from 'sql/workbench/contrib/executionPlan/browser/constants'; import { isString } from 'vs/base/common/types'; import { PlanHeader } from 'sql/workbench/contrib/executionPlan/browser/planHeader'; import { ExecutionPlanPropertiesView } from 'sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesView'; @@ -362,12 +363,47 @@ export class ExecutionPlan implements ISashLayoutProvider { } } + if (node.badges) { + diagramNode.badges = []; + for (let i = 0; i < node.badges.length; i++) { + diagramNode.badges.push(this.getBadgeTypeString(node.badges[i].type)); + } + } + if (node.description) { diagramNode.description = node.description; } return diagramNode; } + private getBadgeTypeString(badgeType: sqlExtHostType.executionPlan.BadgeType): { + type: string, + tooltip: string + } | undefined { + /** + * TODO: Need to figure out if tooltip have to be removed. For now, they are empty + */ + switch (badgeType) { + case sqlExtHostType.executionPlan.BadgeType.Warning: + return { + type: 'warning', + tooltip: '' + }; + case sqlExtHostType.executionPlan.BadgeType.CriticalWarning: + return { + type: 'criticalWarning', + tooltip: '' + }; + case sqlExtHostType.executionPlan.BadgeType.Parallelism: + return { + type: 'parallelism', + tooltip: '' + }; + default: + return undefined; + } + } + private populateEdges(edge: InternalExecutionPlanEdge, diagramEdge: any) { diagramEdge.label = ''; const edgeId = this.createGraphElementId(); @@ -401,7 +437,7 @@ export class ExecutionPlan implements ISashLayoutProvider { let graphRoot: azdata.executionPlan.ExecutionPlanNode = this._graphModel.root; this.populate(graphRoot, diagramRoot); - this.azdataGraphDiagram = new azdataGraph.azdataQueryPlan(container, diagramRoot, executionPlanNodeIconPaths); + this.azdataGraphDiagram = new azdataGraph.azdataQueryPlan(container, diagramRoot, executionPlanNodeIconPaths, badgeIconPaths); this.azdataGraphDiagram.graph.setCellsMovable(false); // preventing drag and drop of graph nodes. this.azdataGraphDiagram.graph.setCellsDisconnectable(false); // preventing graph edges to be disconnected from source and target nodes. @@ -435,7 +471,6 @@ export class ExecutionPlan implements ISashLayoutProvider { }); } - public set graphModel(graph: azdata.executionPlan.ExecutionPlanGraph | undefined) { this._graphModel = graph; if (this._graphModel) { diff --git a/src/sql/workbench/contrib/executionPlan/browser/images/icons/badge_critical_warning.svg b/src/sql/workbench/contrib/executionPlan/browser/images/icons/badge_critical_warning.svg new file mode 100644 index 0000000000..1d4645ac4b --- /dev/null +++ b/src/sql/workbench/contrib/executionPlan/browser/images/icons/badge_critical_warning.svg @@ -0,0 +1 @@ +StatusCriticalError_16x \ No newline at end of file diff --git a/src/sql/workbench/contrib/executionPlan/browser/images/icons/badge_parallel_process.svg b/src/sql/workbench/contrib/executionPlan/browser/images/icons/badge_parallel_process.svg new file mode 100644 index 0000000000..4bd3c09d58 --- /dev/null +++ b/src/sql/workbench/contrib/executionPlan/browser/images/icons/badge_parallel_process.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/src/sql/workbench/contrib/executionPlan/browser/images/icons/badge_warning.svg b/src/sql/workbench/contrib/executionPlan/browser/images/icons/badge_warning.svg new file mode 100644 index 0000000000..9aa86d6e54 --- /dev/null +++ b/src/sql/workbench/contrib/executionPlan/browser/images/icons/badge_warning.svg @@ -0,0 +1 @@ +StatusWarning_16x \ No newline at end of file diff --git a/src/sql/workbench/contrib/executionPlan/browser/media/executionPlan.css b/src/sql/workbench/contrib/executionPlan/browser/media/executionPlan.css index 0fc7fca29f..3473e96518 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/media/executionPlan.css +++ b/src/sql/workbench/contrib/executionPlan/browser/media/executionPlan.css @@ -106,6 +106,7 @@ However we always want it to be the width of the container it is resizing. width: 100%; height: 100%; overflow: scroll; + position: relative; } /* Properties view in execution plan */