diff --git a/.eslintrc.json b/.eslintrc.json index 3bb2037222..5e9f43601c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -761,7 +761,8 @@ "vscode-textmate", "vscode-oniguruma", "iconv-lite-umd", - "jschardet" + "jschardet", + "azdataGraph" ] }, { diff --git a/package.json b/package.json index 6f6fefca25..7098b10ad6 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index 1e0c902535..7338933e8a 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -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() diff --git a/src/sql/azdata.proposed.d.ts b/src/sql/azdata.proposed.d.ts index 02893b0602..375f36c0b9 100644 --- a/src/sql/azdata.proposed.d.ts +++ b/src/sql/azdata.proposed.d.ts @@ -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; + } } diff --git a/src/sql/workbench/contrib/query/browser/queryResultsView.ts b/src/sql/workbench/contrib/query/browser/queryResultsView.ts index 9c98fac4dc..0de3759434 100644 --- a/src/sql/workbench/contrib/query/browser/queryResultsView.ts +++ b/src/sql/workbench/contrib/query/browser/queryResultsView.ts @@ -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)) { diff --git a/src/sql/workbench/contrib/queryplan2/browser/actions/propertiesAction.ts b/src/sql/workbench/contrib/queryplan2/browser/actions/propertiesAction.ts new file mode 100644 index 0000000000..8549ef138c --- /dev/null +++ b/src/sql/workbench/contrib/queryplan2/browser/actions/propertiesAction.ts @@ -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 { + context.propContainer.style.visibility = context.propContainer.style.visibility === 'visible' ? 'hidden' : 'visible'; + } +} diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/collapse.gif b/src/sql/workbench/contrib/queryplan2/browser/images/collapse.gif new file mode 100644 index 0000000000..01e691450c Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/collapse.gif differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/expand.gif b/src/sql/workbench/contrib/queryplan2/browser/images/expand.gif new file mode 100644 index 0000000000..1b24ef1248 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/expand.gif differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/adaptive_join.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/adaptive_join.png new file mode 100644 index 0000000000..a9de8452b0 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/adaptive_join.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/aggregate.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/aggregate.png new file mode 100644 index 0000000000..c9dfa1ab36 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/aggregate.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/apply.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/apply.png new file mode 100644 index 0000000000..0e4972da45 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/apply.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/arithmetic_expression.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/arithmetic_expression.png new file mode 100644 index 0000000000..532e6985c9 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/arithmetic_expression.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/assert.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/assert.png new file mode 100644 index 0000000000..8c828bf9c1 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/assert.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/assign.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/assign.png new file mode 100644 index 0000000000..6006369e1d Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/assign.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/batch_hash_table_build.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/batch_hash_table_build.png new file mode 100644 index 0000000000..f955ff4e3a Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/batch_hash_table_build.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/bitmap.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/bitmap.png new file mode 100644 index 0000000000..9010b0b75b Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/bitmap.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/bookmark_lookup.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/bookmark_lookup.png new file mode 100644 index 0000000000..89d5d11673 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/bookmark_lookup.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/broadcast.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/broadcast.png new file mode 100644 index 0000000000..05735c5a46 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/broadcast.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_delete.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_delete.png new file mode 100644 index 0000000000..6da544c7c1 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_delete.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_insert.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_insert.png new file mode 100644 index 0000000000..4706b31b6d Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_insert.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_merge.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_merge.png new file mode 100644 index 0000000000..c8191635a5 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_merge.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_scan.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_scan.png new file mode 100644 index 0000000000..58faec2603 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_scan.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_seek.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_seek.png new file mode 100644 index 0000000000..13094bad65 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_seek.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_update.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_update.png new file mode 100644 index 0000000000..956a813834 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_index_update.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_update.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_update.png new file mode 100644 index 0000000000..15ccb904b1 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/clustered_update.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/collapse.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/collapse.png new file mode 100644 index 0000000000..7e241912b7 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/collapse.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_delete.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_delete.png new file mode 100644 index 0000000000..cac4731c27 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_delete.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_insert.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_insert.png new file mode 100644 index 0000000000..110242bf4a Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_insert.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_merge.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_merge.png new file mode 100644 index 0000000000..cd5f7643a2 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_merge.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_scan.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_scan.png new file mode 100644 index 0000000000..de030b6b4e Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_scan.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_update.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_update.png new file mode 100644 index 0000000000..f0b2ad13e1 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/columnstore_index_update.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/compute_scalar.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/compute_scalar.png new file mode 100644 index 0000000000..7ce66ceac9 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/compute_scalar.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/compute_to_control_node.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/compute_to_control_node.png new file mode 100644 index 0000000000..98c0c95e14 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/compute_to_control_node.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/concatenation.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/concatenation.png new file mode 100644 index 0000000000..214d68358f Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/concatenation.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/const_table_get.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/const_table_get.png new file mode 100644 index 0000000000..0f32261c3b Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/const_table_get.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/constant_scan.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/constant_scan.png new file mode 100644 index 0000000000..88c1354bf0 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/constant_scan.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/control_to_compute_nodes.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/control_to_compute_nodes.png new file mode 100644 index 0000000000..47066d9737 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/control_to_compute_nodes.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/convert.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/convert.png new file mode 100644 index 0000000000..badf83c7d0 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/convert.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/cursor_catch_all.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/cursor_catch_all.png new file mode 100644 index 0000000000..7344f5dd65 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/cursor_catch_all.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/declare.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/declare.png new file mode 100644 index 0000000000..7d7f97b31d Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/declare.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/delete.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/delete.png new file mode 100644 index 0000000000..2d1e12253b Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/delete.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/deleted_scan.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/deleted_scan.png new file mode 100644 index 0000000000..84e6c0ab96 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/deleted_scan.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/dynamic.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/dynamic.png new file mode 100644 index 0000000000..01e92669c1 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/dynamic.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_broadcast.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_broadcast.png new file mode 100644 index 0000000000..373f018029 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_broadcast.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_export.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_export.png new file mode 100644 index 0000000000..7533114847 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_export.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_local_streaming.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_local_streaming.png new file mode 100644 index 0000000000..48889aedc3 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_local_streaming.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_round_robin.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_round_robin.png new file mode 100644 index 0000000000..b0202d4ff1 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_round_robin.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_shuffle.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_shuffle.png new file mode 100644 index 0000000000..6d7c24cfab Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/external_shuffle.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/fetch_query.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/fetch_query.png new file mode 100644 index 0000000000..a1fd0f121d Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/fetch_query.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/filter.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/filter.png new file mode 100644 index 0000000000..af726e9068 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/filter.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/foreign_key_references_check.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/foreign_key_references_check.png new file mode 100644 index 0000000000..f87b6443fa Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/foreign_key_references_check.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/get.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/get.png new file mode 100644 index 0000000000..79e832f23e Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/get.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/group_by_aggregate.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/group_by_aggregate.png new file mode 100644 index 0000000000..cdb1bf9e9c Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/group_by_aggregate.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/hash_match.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/hash_match.png new file mode 100644 index 0000000000..fb78ddcfd2 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/hash_match.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/hash_match_root.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/hash_match_root.png new file mode 100644 index 0000000000..07f46f53f8 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/hash_match_root.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/hash_match_team.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/hash_match_team.png new file mode 100644 index 0000000000..c1070796e2 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/hash_match_team.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/if.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/if.png new file mode 100644 index 0000000000..0aedbcb369 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/if.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_delete.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_delete.png new file mode 100644 index 0000000000..c367019fa1 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_delete.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_insert.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_insert.png new file mode 100644 index 0000000000..723e71a571 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_insert.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_scan.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_scan.png new file mode 100644 index 0000000000..e373d6c883 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_scan.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_seek.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_seek.png new file mode 100644 index 0000000000..093805cddf Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_seek.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_spool.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_spool.png new file mode 100644 index 0000000000..5d0fa8f620 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_spool.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_update.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_update.png new file mode 100644 index 0000000000..0b4570e48f Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/index_update.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/insert.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/insert.png new file mode 100644 index 0000000000..87fca57487 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/insert.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/inserted_scan.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/inserted_scan.png new file mode 100644 index 0000000000..4f2db17c90 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/inserted_scan.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/intrinsic.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/intrinsic.png new file mode 100644 index 0000000000..8c5b614ed4 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/intrinsic.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/iterator_catch_all.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/iterator_catch_all.png new file mode 100644 index 0000000000..5a2d728d68 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/iterator_catch_all.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/join.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/join.png new file mode 100644 index 0000000000..aefe5b4451 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/join.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/keyset.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/keyset.png new file mode 100644 index 0000000000..f6371f4cb2 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/keyset.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/language_construct_catch_all.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/language_construct_catch_all.png new file mode 100644 index 0000000000..2d247ce75a Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/language_construct_catch_all.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/locate.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/locate.png new file mode 100644 index 0000000000..5cba66792e Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/locate.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/log_row_scan.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/log_row_scan.png new file mode 100644 index 0000000000..bfe7875f3d Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/log_row_scan.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/merge_interval.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/merge_interval.png new file mode 100644 index 0000000000..98b2aef92d Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/merge_interval.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/merge_join.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/merge_join.png new file mode 100644 index 0000000000..b9c1bceed0 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/merge_join.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/nested_loops.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/nested_loops.png new file mode 100644 index 0000000000..89f6c764ce Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/nested_loops.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/parallelism.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/parallelism.png new file mode 100644 index 0000000000..45d28d806e Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/parallelism.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/parameter_table_scan.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/parameter_table_scan.png new file mode 100644 index 0000000000..5dd33d650d Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/parameter_table_scan.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/population_query.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/population_query.png new file mode 100644 index 0000000000..172c90e82b Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/population_query.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/predict.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/predict.png new file mode 100644 index 0000000000..deb2b30934 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/predict.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/print.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/print.png new file mode 100644 index 0000000000..9ecab7306c Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/print.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/project.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/project.png new file mode 100644 index 0000000000..be9d1765b4 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/project.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/rank.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/rank.png new file mode 100644 index 0000000000..008459045f Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/rank.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/refresh_query.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/refresh_query.png new file mode 100644 index 0000000000..eeb4e75161 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/refresh_query.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_delete.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_delete.png new file mode 100644 index 0000000000..6c4d1b7b70 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_delete.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_index_scan.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_index_scan.png new file mode 100644 index 0000000000..1f06dd599b Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_index_scan.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_index_seek.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_index_seek.png new file mode 100644 index 0000000000..94e66cb88a Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_index_seek.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_insert.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_insert.png new file mode 100644 index 0000000000..9a22f89ce3 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_insert.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_query.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_query.png new file mode 100644 index 0000000000..073dcef4c7 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_query.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_scan.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_scan.png new file mode 100644 index 0000000000..24a43a95fe Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_scan.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_update.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_update.png new file mode 100644 index 0000000000..f027393cf4 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/remote_update.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/result.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/result.png new file mode 100644 index 0000000000..e3545a1b2d Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/result.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/rid_lookup.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/rid_lookup.png new file mode 100644 index 0000000000..83ad0c04d1 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/rid_lookup.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/row_count_spool.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/row_count_spool.png new file mode 100644 index 0000000000..40ee6c52b0 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/row_count_spool.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/segment.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/segment.png new file mode 100644 index 0000000000..64e1218f63 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/segment.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/sequence.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/sequence.png new file mode 100644 index 0000000000..1a5aeb8c2a Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/sequence.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/sequence_project.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/sequence_project.png new file mode 100644 index 0000000000..29dc7b8978 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/sequence_project.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/set_function.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/set_function.png new file mode 100644 index 0000000000..7272565f68 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/set_function.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/shuffle.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/shuffle.png new file mode 100644 index 0000000000..dafa538313 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/shuffle.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/single_source_round_robin.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/single_source_round_robin.png new file mode 100644 index 0000000000..e77bd9fa30 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/single_source_round_robin.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/single_source_shuffle.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/single_source_shuffle.png new file mode 100644 index 0000000000..f8b27a7020 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/single_source_shuffle.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/snapshot.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/snapshot.png new file mode 100644 index 0000000000..110e1912ef Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/snapshot.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/sort.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/sort.png new file mode 100644 index 0000000000..5d36843de4 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/sort.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/split.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/split.png new file mode 100644 index 0000000000..37c6369d8f Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/split.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/spool.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/spool.png new file mode 100644 index 0000000000..cc2a20d01b Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/spool.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/sql.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/sql.png new file mode 100644 index 0000000000..112e580ad5 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/sql.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/stream_aggregate.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/stream_aggregate.png new file mode 100644 index 0000000000..04285c1a3e Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/stream_aggregate.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/switch.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/switch.png new file mode 100644 index 0000000000..20d342a800 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/switch.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_delete.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_delete.png new file mode 100644 index 0000000000..09ee86255c Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_delete.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_insert.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_insert.png new file mode 100644 index 0000000000..3b515fdae4 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_insert.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_merge.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_merge.png new file mode 100644 index 0000000000..f390461bb5 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_merge.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_scan.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_scan.png new file mode 100644 index 0000000000..ad807febdd Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_scan.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_spool.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_spool.png new file mode 100644 index 0000000000..3ba8e7cb79 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_spool.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_update.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_update.png new file mode 100644 index 0000000000..171bc4f90a Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_update.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_valued_function.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_valued_function.png new file mode 100644 index 0000000000..6969e59549 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/table_valued_function.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/top.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/top.png new file mode 100644 index 0000000000..e47f12210b Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/top.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/trim.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/trim.png new file mode 100644 index 0000000000..b398045fd9 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/trim.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/udx.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/udx.png new file mode 100644 index 0000000000..59b331eec3 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/udx.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/union.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/union.png new file mode 100644 index 0000000000..4bf96a9dbc Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/union.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/union_all.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/union_all.png new file mode 100644 index 0000000000..d19964750a Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/union_all.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/update.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/update.png new file mode 100644 index 0000000000..ea13c72b94 Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/update.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/images/icons/window_aggregate.png b/src/sql/workbench/contrib/queryplan2/browser/images/icons/window_aggregate.png new file mode 100644 index 0000000000..9f2f161c5e Binary files /dev/null and b/src/sql/workbench/contrib/queryplan2/browser/images/icons/window_aggregate.png differ diff --git a/src/sql/workbench/contrib/queryplan2/browser/media/queryPlan2.css b/src/sql/workbench/contrib/queryplan2/browser/media/queryPlan2.css new file mode 100644 index 0000000000..206b41c403 --- /dev/null +++ b/src/sql/workbench/contrib/queryplan2/browser/media/queryPlan2.css @@ -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. + *--------------------------------------------------------------------------------------------*/ + +.qp-container .query-plan { + width: 100%; + height: 500px; + position: relative; + border-top: 1px solid; +} + +.qp-container .query-plan .actionbar-container { +height: 100%; +width: 30px; +position: absolute; +top: 0px; +right: 0px; +} + +.qp-container .query-plan .properties-container { + position: absolute; + top: 0px; + right: 32px; + height: 100%; + overflow-y: scroll; + background-color: #eeeeee; + width: 510px; +} + +.qp-container .prop-table-header { + font-weight: bold; +} + +.qp-container .properties-header { + font-weight: bold; + padding: 5px; +} + +.qp-container .properties-toggle { + height: 9px; + width: 9px; + display: inline-block; +} + +.qp-container .properties-toggle .expand { + background: url(../images/expand.gif) no-repeat center center; +} + +.qp-container .properties-toggle .collapse { + background: url(../images/collapse.gif) no-repeat center center; +} + +.qp-container .mxTooltip { + -webkit-box-shadow: 3px 3px 12px #C0C0C0; + -moz-box-shadow: 3px 3px 12px #C0C0C0; + box-shadow: 3px 3px 12px #C0C0C0; + background: #FFFFCC; + border-style: solid; + border-width: 1px; + border-color: black; + font-family: Arial; + font-size: 8pt; + position: absolute; + cursor: default; + padding: 4px; + color: black; + z-index: 3; +} diff --git a/src/sql/workbench/contrib/queryplan2/browser/queryPlan.ts b/src/sql/workbench/contrib/queryplan2/browser/queryPlan.ts new file mode 100644 index 0000000000..7aa0194590 --- /dev/null +++ b/src/sql/workbench/contrib/queryplan2/browser/queryPlan.ts @@ -0,0 +1,582 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import 'vs/css!./media/queryPlan2'; +import type * as azdata from 'azdata'; +import { IPanelView, IPanelTab } from 'sql/base/browser/ui/panel/panel'; +import { URI } from 'vs/base/common/uri'; +import { localize } from 'vs/nls'; +import { dispose } from 'vs/base/common/lifecycle'; +import { IConfigurationRegistry, Extensions as ConfigExtensions } from 'vs/platform/configuration/common/configurationRegistry'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; +import * as DOM from 'vs/base/browser/dom'; +import { PropertiesAction } from 'sql/workbench/contrib/queryplan2/browser/actions/propertiesAction'; +import * as azdataGraphModule from 'azdataGraph'; +import { escape } from 'sql/base/common/strings'; +let azdataGraph = azdataGraphModule(); + +export class QueryPlan2Tab implements IPanelTab { + public readonly title = localize('queryPlanTitle', "Query Plan"); + public readonly identifier = 'QueryPlan2Tab'; + public readonly view: QueryPlan2View; + + constructor() { + this.view = new QueryPlan2View(); + } + + public dispose() { + dispose(this.view); + } + + public clear() { + this.view.clear(); + } +} + +export class QueryPlan2View implements IPanelView { + private _qps?: QueryPlan2[] = []; + private _graphs?: azdata.QueryPlanGraph[] = []; + private _container = DOM.$('.qp-container'); + + public render(container: HTMLElement): void { + container.appendChild(this._container); + this._container.style.overflow = 'scroll'; + } + + dispose() { + this._container.remove(); + delete this._qps; + delete this._graphs; + } + + public layout(dimension: DOM.Dimension): void { + this._container.style.width = dimension.width + 'px'; + this._container.style.height = dimension.height + 'px'; + } + + public clear() { + this._qps = []; + this._graphs = []; + DOM.clearNode(this._container); + } + + public addGraphs(newGraphs: azdata.QueryPlanGraph[]) { + newGraphs.forEach(g => { + const qp2 = new QueryPlan2(this._container, this._qps.length + 1); + qp2.graph = g; + this._qps.push(qp2); + this._graphs.push(g); + this.updateRelativeCosts(); + }); + } + + private updateRelativeCosts() { + const sum = this._graphs.reduce((prevCost: number, cg) => { + return prevCost += cg.root.subTreeCost + cg.root.cost; + }, 0); + + if (sum > 0) { + this._qps.forEach(qp => { + qp.relativeCost = ((qp.graph.root.subTreeCost + qp.graph.root.cost) / sum) * 100; + }); + } + } +} + +export class QueryPlan2 { + private _graph?: azdata.QueryPlanGraph; + private _relativeCost?: globalThis.Text; + private _actionBar: ActionBar; + private _table: Slick.Grid; + private _dataView: Slick.Data.DataView; + private _container: HTMLElement; + private _actionBarContainer: HTMLElement; + private _data: any[]; + private _iconMap: any = new Object(); + private _iconPaths: any = new Object(); + + public propContainer: HTMLElement; + + constructor( + parent: HTMLElement, + private _graphIndex: number, + + ) { + this._container = DOM.$('.query-plan'); + parent.appendChild(this._container); + + + this._actionBarContainer = DOM.$('.actionbar-container'); + this._actionBar = new ActionBar(this._actionBarContainer, { + orientation: ActionsOrientation.VERTICAL, context: this + }); + + this.propContainer = DOM.$('.properties-container'); + const propHeader = document.createElement('div'); + propHeader.className = 'properties-header'; + propHeader.innerText = 'Properties'; + this.propContainer.appendChild(propHeader); + + this.propContainer.style.visibility = 'hidden'; + + this._dataView = new Slick.Data.DataView({ inlineFilters: false }); + let self = this; + this._data = []; + const TaskNameFormatter = function (row, cell, value, columnDef, dataContext) { + value = escape(value); + const spacer = ''; + const idx = self._dataView.getIdxById(dataContext.id); + if (self._data[idx + 1] && self._data[idx + 1].indent > self._data[idx].indent) { + if (dataContext._collapsed) { + return spacer + ' ' + value; + } else { + return spacer + ' ' + value; + } + } else { + return spacer + ' ' + value; + } + }; + + const columns: Slick.Column[] = [ + { + id: 'name', + name: 'Name', + field: 'name', + width: 250, + editor: Slick.Editors.Text, + formatter: TaskNameFormatter, + headerCssClass: 'prop-table-header' + }, + { + id: 'value', + name: 'Value', + field: 'propValue', + width: 250, + editor: Slick.Editors.Text, + headerCssClass: 'prop-table-header' + } + ]; + + const options: Slick.GridOptions = { + editable: false, + enableAddRow: false, + enableCellNavigation: true, + autoHeight: true + }; + + const tableContainer = DOM.$('.table-container'); + tableContainer.style.height = '500px'; + tableContainer.style.width = '490px'; + this.propContainer.appendChild(tableContainer); + this._table = new Slick.Grid(tableContainer, this._dataView, columns, options); + + this._table.onClick.subscribe((e: any, args) => { + + const item = this._dataView.getItem(args.row); + if (item) { + item._collapsed = !item._collapsed; + this._dataView.updateItem(item.id, item); + } + e.stopImmediatePropagation(); + }); + + this._dataView.setFilter((item) => { + if (item.parent !== null) { + let parent = this._data[item.parent]; + while (parent) { + if (parent._collapsed) { + return false; + } + + parent = this._data[parent.parent]; + } + } + return true; + }); + + + // wire up model events to drive the grid + this._dataView.onRowCountChanged.subscribe((e, args) => { + this._table.updateRowCount(); + this._table.render(); + }); + + this._dataView.onRowsChanged.subscribe((e, args) => { + this._table.invalidateRows(args.rows); + this._table.render(); + }); + + const actions = [ + new PropertiesAction() + ]; + this._actionBar.push(actions, { icon: true, label: false }); + + this._iconMap['Adaptive_Join_32x.ico'] = 'adaptiveJoin'; + this._iconMap['Assert_32x.ico'] = 'assert'; + this._iconMap['Bitmap_32x.ico'] = 'bitmap'; + this._iconMap['Clustered_index_delete_32x.ico'] = 'clusteredIndexDelete'; + this._iconMap['Clustered_index_insert_32x.ico'] = 'ClusteredIndexInsert'; + this._iconMap['Clustered_index_scan_32x.ico'] = 'ClusteredIndexScan'; + this._iconMap['Clustered_index_seek_32x.ico'] = 'ClusteredIndexSeek'; + this._iconMap['Clustered_index_update_32x.ico'] = 'ClusteredIndexUpdate'; + this._iconMap['Clustered_index_merge_32x.icoo'] = 'ClusteredIndexMerge'; + + + this._iconMap['Filter_32x.ico'] = 'filter'; + this._iconMap['Clustered_index_scan_32x.ico'] = 'clusteredIndexScan'; + this._iconMap['Clustered_index_seek_32x.ico'] = 'clusteredIndexSeek'; + this._iconMap['Compute_scalar_32x.ico'] = 'computeScalar'; + this._iconMap['Concatenation_32x.ico'] = 'concatenation'; + + this._iconMap['Concatenation_32x.ico'] = 'concatenation'; + + this._iconMap['Nested_loops_32x.ico'] = 'nestedLoops'; + this._iconMap['Result_32x.ico'] = 'result'; + this._iconMap['Table_spool_32x.ico'] = 'tableSpool'; + this._iconMap['Top_32x.ico'] = 'top'; + let imageBasePath = URI.parse(decodeURI(require.toUrl('./images/icons/'))).fsPath; + this._iconPaths = + { + // generic icons + iteratorCatchAll: imageBasePath + 'iterator_catch_all.png', + + cursorCatchAll: imageBasePath + 'cursor_catch_all.png', + + languageConstructCatchAll: imageBasePath + 'language_construct_catch_all.png', + + // operator icons + adaptiveJoin: imageBasePath + 'adaptive_join.png', + + assert: imageBasePath + 'assert.png', + + bitmap: imageBasePath + 'bitmap.png', + + clusteredIndexDelete: imageBasePath + 'clustered_index_delete.png', + + clusteredIndexInsert: imageBasePath + 'clustered_index_insert.png', + + clusteredIndexScan: imageBasePath + 'clustered_index_scan.png', + + clusteredIndexSeek: imageBasePath + 'clustered_index_seek.png', + + clusteredIndexUpdate: imageBasePath + 'clustered_index_update.png', + + clusteredIndexMerge: imageBasePath + 'clustered_index_merge.png', + + clusteredUpdate: imageBasePath + 'clustered_update.png', + + collapse: imageBasePath + 'collapse.png', + + computeScalar: imageBasePath + 'compute_scalar.png', + + concatenation: imageBasePath + 'concatenation.png', + + constantScan: imageBasePath + 'constant_scan.png', + + deletedScan: imageBasePath + 'deleted_scan.png', + + filter: imageBasePath + 'filter.png', + + hashMatch: imageBasePath + 'hash_match.png', + + indexDelete: imageBasePath + 'index_delete.png', + + indexInsert: imageBasePath + 'index_insert.png', + + indexScan: imageBasePath + 'index_scan.png', + + columnstoreIndexDelete: imageBasePath + 'columnstore_index_delete.png', + + columnstoreIndexInsert: imageBasePath + 'columnstore_index_insert.png', + + columnstoreIndexMerge: imageBasePath + 'columnstore_index_merge.png', + + columnstoreIndexScan: imageBasePath + 'columnstore_index_scan.png', + + columnstoreIndexUpdate: imageBasePath + 'columnstore_index_update.png', + + indexSeek: imageBasePath + 'index_seek.png', + + indexSpool: imageBasePath + 'index_spool.png', + + indexUpdate: imageBasePath + 'index_update.png', + + insertedScan: imageBasePath + 'inserted_scan.png', + + logRowScan: imageBasePath + 'log_row_scan.png', + + mergeInterval: imageBasePath + 'merge_interval.png', + + mergeJoin: imageBasePath + 'merge_join.png', + + nestedLoops: imageBasePath + 'nested_loops.png', + + parallelism: imageBasePath + 'parallelism.png', + + parameterTableScan: imageBasePath + 'parameter_table_scan.png', + + print: imageBasePath + 'print.png', + + rank: imageBasePath + 'rank.png', + + foreignKeyReferencesCheck: imageBasePath + 'foreign_key_references_check.png', + + remoteDelete: imageBasePath + 'remote_delete.png', + + remoteIndexScan: imageBasePath + 'remote_index_scan.png', + + remoteIndexSeek: imageBasePath + 'remote_index_seek.png', + + remoteInsert: imageBasePath + 'remote_insert.png', + + remoteQuery: imageBasePath + 'remote_query.png', + + remoteScan: imageBasePath + 'remote_scan.png', + + remoteUpdate: imageBasePath + 'remote_update.png', + + ridLookup: imageBasePath + 'rid_lookup.png', + + rowCountSpool: imageBasePath + 'row_count_spool.png', + + segment: imageBasePath + 'segment.png', + + sequence: imageBasePath + 'sequence.png', + + sequenceProject: imageBasePath + 'sequence_project.png', + + sort: imageBasePath + 'sort.png', + + split: imageBasePath + 'split.png', + + streamAggregate: imageBasePath + 'stream_aggregate.png', + + switchStatement: imageBasePath + 'switch.png', + + tableValuedFunction: imageBasePath + 'table_valued_function.png', + + tableDelete: imageBasePath + 'table_delete.png', + + tableInsert: imageBasePath + 'table_insert.png', + + tableScan: imageBasePath + 'table_scan.png', + + tableSpool: imageBasePath + 'table_spool.png', + + tableUpdate: imageBasePath + 'table_update.png', + + tableMerge: imageBasePath + 'table_merge.png', + + tfp: imageBasePath + 'predict.png', + + top: imageBasePath + 'top.png', + + udx: imageBasePath + 'udx.png', + + batchHashTableBuild: imageBasePath + 'batch_hash_table_build.png', + + windowSpool: imageBasePath + 'table_spool.png', + + windowAggregate: imageBasePath + 'window_aggregate.png', + + // cursor operators + fetchQuery: imageBasePath + 'fetch_query.png', + + populateQuery: imageBasePath + 'population_query.png', + + refreshQuery: imageBasePath + 'refresh_query.png', + + // shiloh operators + result: imageBasePath + 'result.png', + + aggregate: imageBasePath + 'aggregate.png', + + assign: imageBasePath + 'assign.png', + + arithmeticExpression: imageBasePath + 'arithmetic_expression.png', + + bookmarkLookup: imageBasePath + 'bookmark_lookup.png', + + convert: imageBasePath + 'convert.png', + + declare: imageBasePath + 'declare.png', + + deleteOperator: imageBasePath + 'delete.png', + + dynamic: imageBasePath + 'dynamic.png', + + hashMatchRoot: imageBasePath + 'hash_match_root.png', + + hashMatchTeam: imageBasePath + 'hash_match_team.png', + + ifOperator: imageBasePath + 'if.png', + + insert: imageBasePath + 'insert.png', + + intrinsic: imageBasePath + 'intrinsic.png', + + keyset: imageBasePath + 'keyset.png', + + locate: imageBasePath + 'locate.png', + + populationQuery: imageBasePath + 'population_query.png', + + setFunction: imageBasePath + 'set_function.png', + + snapshot: imageBasePath + 'snapshot.png', + + spool: imageBasePath + 'spool.png', + + tsql: imageBasePath + 'sql.png', + + update: imageBasePath + 'update.png', + + // fake operators + keyLookup: imageBasePath + 'bookmark_lookup.png', + + // PDW operators + apply: imageBasePath + 'apply.png', + + broadcast: imageBasePath + 'broadcast.png', + + computeToControlNode: imageBasePath + 'compute_to_control_node.png', + + constTableGet: imageBasePath + 'const_table_get.png', + + controlToComputeNodes: imageBasePath + 'control_to_compute_nodes.png', + + externalBroadcast: imageBasePath + 'external_broadcast.png', + + externalExport: imageBasePath + 'external_export.png', + + externalLocalStreaming: imageBasePath + 'external_local_streaming.png', + + externalRoundRobin: imageBasePath + 'external_round_robin.png', + + externalShuffle: imageBasePath + 'external_shuffle.png', + + get: imageBasePath + 'get.png', + + groupByApply: imageBasePath + 'apply.png', + + groupByAggregate: imageBasePath + 'group_by_aggregate.png', + + join: imageBasePath + 'join.png', + + localCube: imageBasePath + 'intrinsic.png', + + project: imageBasePath + 'project.png', + + shuffle: imageBasePath + 'shuffle.png', + + singleSourceRoundRobin: imageBasePath + 'single_source_round_robin.png', + + singleSourceShuffle: imageBasePath + 'single_source_shuffle.png', + + trim: imageBasePath + 'trim.png', + + union: imageBasePath + 'union.png', + + unionAll: imageBasePath + 'union_all.png' + }; + } + + private populate(node: azdata.QueryPlanGraphNode, diagramNode: any): any { + + diagramNode.label = node.name; + if (node.properties && node.properties.length > 0) { + diagramNode.metrics = node.properties.map(e => { return { name: e.name, value: e.formattedValue.substring(0, 75) }; }); + } + + let icon = this._iconMap[node.type]; + if (icon) { + diagramNode.icon = icon; + } + + if (node.children) { + diagramNode.children = []; + for (let i = 0; i < node.children.length; ++i) { + diagramNode.children.push(this.populate(node.children[i], new Object())); + } + } + return diagramNode; + } + + private createPlanDiagram(container: HTMLDivElement): void { + let diagramRoot: any = new Object(); + let graphRoot: azdata.QueryPlanGraphNode = this._graph.root; + this.populate(graphRoot, diagramRoot); + + new azdataGraph.azdataQueryPlan(container, diagramRoot, this._iconPaths); + } + + + public set graph(graph: azdata.QueryPlanGraph | undefined) { + this._graph = graph; + if (this._graph) { + this._container.appendChild(document.createTextNode(localize('queryIndex', "Query {0}: ", this._graphIndex))); + this._relativeCost = document.createTextNode(localize('relativeToTheScript', "(relative to the script):")); + this._container.appendChild(this._relativeCost); + this._container.appendChild(document.createElement('br')); + this._container.appendChild(document.createTextNode(`${graph.query}`)); + let diagramContainer = document.createElement('div'); + this.createPlanDiagram(diagramContainer); + this._container.appendChild(diagramContainer); + + this._container.appendChild(this.propContainer); + this.setData(this._graph.root.properties); + this._container.appendChild(this._actionBarContainer); + } + } + + public get graph(): azdata.QueryPlanGraph | undefined { + return this._graph; + } + + public set relativeCost(newCost: number) { + this._relativeCost.nodeValue = localize('relativeToTheScriptWithCost', "(relative to the script): {0}%", newCost.toFixed(2)); + } + + public setData(props: azdata.QueryPlanGraphElementProperty[]): void { + this._data = []; + props.forEach((p, i) => { + this._data.push({ + id: p.name, + name: p.name, + propValue: p.formattedValue, + _collapsed: true + }); + }); + this._dataView.beginUpdate(); + this._dataView.setItems(this._data); + this._dataView.endUpdate(); + this._dataView.refresh(); + this._table.autosizeColumns(); + this._table.updateRowCount(); + this._table.resizeCanvas(); + this._table.render(); + } +} + +/** + * Registering a feature flag for query plan. + * TODO: This should be removed before taking the feature to public preview. + */ +const QUERYPLAN2_CONFIG_ID = 'queryPlan2'; +Registry.as(ConfigExtensions.Configuration).registerConfiguration({ + id: QUERYPLAN2_CONFIG_ID, + title: localize('queryPlan2.configTitle', "Query Plan"), + type: 'object', + properties: { + 'queryPlan2.enableFeature': { + 'type': 'boolean', + 'default': false, + 'description': localize('queryPlan2.featureEnabledDescription', "Controls whether the new query plan feature is enabled. Default value is false.") + } + } +}); + + diff --git a/src/sql/workbench/services/query/common/queryManagement.ts b/src/sql/workbench/services/query/common/queryManagement.ts index a7b9e80256..bc17ee044a 100644 --- a/src/sql/workbench/services/query/common/queryManagement.ts +++ b/src/sql/workbench/services/query/common/queryManagement.ts @@ -17,6 +17,7 @@ import { ResultSetSubset } from 'sql/workbench/services/query/common/query'; import { isUndefined } from 'vs/base/common/types'; import { ILogService } from 'vs/platform/log/common/log'; import * as nls from 'vs/nls'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; export const SERVICE_ID = 'queryManagementService'; @@ -119,7 +120,8 @@ export class QueryManagementService implements IQueryManagementService { constructor( @IConnectionManagementService private _connectionService: IConnectionManagementService, @IAdsTelemetryService private _telemetryService: IAdsTelemetryService, - @ILogService private _logService: ILogService + @ILogService private _logService: ILogService, + @IConfigurationService private _configurationService: IConfigurationService ) { } @@ -329,6 +331,9 @@ export class QueryManagementService implements IQueryManagementService { public onResultSetUpdated(resultSetInfo: azdata.QueryExecuteResultSetNotificationParams): void { this._notify(resultSetInfo.ownerUri, (runner: QueryRunner) => { runner.handleResultSetUpdated(resultSetInfo.resultSetSummary); + if (resultSetInfo.executionPlans && this._configurationService.getValue('queryPlan2.enableFeature')) { + runner.handleQueryPlan2Available(resultSetInfo.executionPlans); + } }); } diff --git a/src/sql/workbench/services/query/common/queryModel.ts b/src/sql/workbench/services/query/common/queryModel.ts index 374998cdd1..3d2fdf6091 100644 --- a/src/sql/workbench/services/query/common/queryModel.ts +++ b/src/sql/workbench/services/query/common/queryModel.ts @@ -15,7 +15,8 @@ import { EditCreateRowResult, EditRevertCellResult, ExecutionPlanOptions, - queryeditor + queryeditor, + QueryPlanGraph } from 'azdata'; import { QueryInfo } from 'sql/workbench/services/query/common/queryModelService'; import { IRange } from 'vs/editor/common/core/range'; @@ -30,6 +31,12 @@ export interface IQueryPlanInfo { planXml: string; } +export interface IQueryPlan2Info { + providerId: string; + fileUri: string; + planGraphs: QueryPlanGraph[]; +} + export interface IQueryInfo { range: IRange[]; messages: IQueryMessage[]; diff --git a/src/sql/workbench/services/query/common/queryModelService.ts b/src/sql/workbench/services/query/common/queryModelService.ts index 9b38a5fa4e..1733ec1605 100644 --- a/src/sql/workbench/services/query/common/queryModelService.ts +++ b/src/sql/workbench/services/query/common/queryModelService.ts @@ -352,6 +352,21 @@ export class QueryModelService implements IQueryModelService { this._onQueryEvent.fire(event); }); + queryRunner.onQueryPlan2Available(qp2Info => { + // fire extensibility API event + let event: IQueryEvent = { + type: 'executionPlan', + uri: qp2Info.fileUri, + queryInfo: + { + range: info.range!, + messages: info.queryRunner!.messages + }, + params: qp2Info.planGraphs + }; + this._onQueryEvent.fire(event); + }); + queryRunner.onVisualize(resultSetInfo => { let event: IQueryEvent = { type: 'visualize', diff --git a/src/sql/workbench/services/query/common/queryRunner.ts b/src/sql/workbench/services/query/common/queryRunner.ts index e946b12f01..673776d435 100644 --- a/src/sql/workbench/services/query/common/queryRunner.ts +++ b/src/sql/workbench/services/query/common/queryRunner.ts @@ -6,9 +6,10 @@ import { IQueryManagementService, QueryCancelResult, ExecutionPlanOptions } from 'sql/workbench/services/query/common/queryManagement'; import * as Utils from 'sql/platform/connection/common/utils'; import { Deferred } from 'sql/base/common/promise'; -import { IQueryPlanInfo } from 'sql/workbench/services/query/common/queryModel'; +import { IQueryPlanInfo, IQueryPlan2Info } from 'sql/workbench/services/query/common/queryModel'; import { ResultSerializer, SaveFormat } from 'sql/workbench/services/query/common/resultSerializer'; +import * as azdata from 'azdata'; import * as nls from 'vs/nls'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import * as types from 'vs/base/common/types'; @@ -72,6 +73,9 @@ export default class QueryRunner extends Disposable { private readonly _onQueryPlanAvailable = this._register(new Emitter()); public readonly onQueryPlanAvailable = this._onQueryPlanAvailable.event; + private readonly _onQueryPlan2Available = this._register(new Emitter()); + public readonly onQueryPlan2Available = this._onQueryPlan2Available.event; + private readonly _onVisualize = this._register(new Emitter()); public readonly onVisualize = this._onVisualize.event; @@ -383,6 +387,16 @@ export default class QueryRunner extends Disposable { } } + public handleQueryPlan2Available(queryPlans: azdata.QueryPlanGraph[] | undefined) { + if (queryPlans) { + this._onQueryPlan2Available.fire({ + providerId: mssqlProviderName, + fileUri: this.uri, + planGraphs: queryPlans + }); + } + } + /** * Handle a Mssage from the service layer */ diff --git a/src/typings/azdataGraph.d.ts b/src/typings/azdataGraph.d.ts new file mode 100644 index 0000000000..2257f76bc3 --- /dev/null +++ b/src/typings/azdataGraph.d.ts @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare class azdataQueryPlan { + public isEnabled(): number; + public init(): void; +} diff --git a/yarn.lock b/yarn.lock index 6349d5ef26..9395bdb52c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1831,6 +1831,10 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== +"azdataGraph@github:Microsoft/azdataGraph#0.0.5": + version "0.0.5" + resolved "https://codeload.github.com/Microsoft/azdataGraph/tar.gz/7812950d661758016962897ec4704a39b118b001" + azure-storage@^2.10.2: version "2.10.2" resolved "https://registry.yarnpkg.com/azure-storage/-/azure-storage-2.10.2.tgz#3bcabdbf10e72fd0990db81116e49023c4a675b6"