From 0f54d60921e78410dd9a43a6520704831965704c Mon Sep 17 00:00:00 2001 From: Aasim Khan Date: Wed, 19 Jan 2022 14:31:19 -0800 Subject: [PATCH] Parsing nested properties in show plan nodes. (#1351) * Parsing nested properties in show plan nodes. * Creating a base class for ExecutionGraphProp Adding a simple test to see if the nested props are parsed correctly. * Fixing doc comment * simplifying class name --- .../ShowPlan/Contracts/ExecutionPlanGraph.cs | 26 ++++++++++---- .../ShowPlan/ShowPlanGraphUtils.cs | 36 ++++++++++++++----- .../ShowPlan/ShowPlanTests.cs | 32 ++++++++++++++--- 3 files changed, 74 insertions(+), 20 deletions(-) diff --git a/src/Microsoft.SqlTools.ServiceLayer/ShowPlan/Contracts/ExecutionPlanGraph.cs b/src/Microsoft.SqlTools.ServiceLayer/ShowPlan/Contracts/ExecutionPlanGraph.cs index 94b46a89..ecee61e4 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ShowPlan/Contracts/ExecutionPlanGraph.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ShowPlan/Contracts/ExecutionPlanGraph.cs @@ -47,7 +47,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ShowPlan /// /// Node properties to be shown in the tooltip /// - public List Properties { get; set; } + public List Properties { get; set; } /// /// Display name for the node /// @@ -64,17 +64,13 @@ namespace Microsoft.SqlTools.ServiceLayer.ShowPlan public List Edges { get; set; } } - public class ExecutionPlanGraphElementProperties + public class ExecutionPlanGraphPropertyBase { /// /// Name of the property /// public string Name { get; set; } /// - /// Formatted value for the property - /// - public string FormattedValue { get; set; } - /// /// Flag to show/hide props in tooltip /// public bool ShowInTooltip { get; set; } @@ -88,6 +84,22 @@ namespace Microsoft.SqlTools.ServiceLayer.ShowPlan public bool IsLongString { get; set; } } + public class NestedExecutionPlanGraphProperty: ExecutionPlanGraphPropertyBase + { + /// + /// In case of nested properties, the value field is a list of properties. + /// + public List Value { get; set; } + } + + public class ExecutionPlanGraphProperty : ExecutionPlanGraphPropertyBase + { + /// + /// Formatted value for the property + /// + public string Value { get; set; } + } + public class ExecutionPlanEdges { /// @@ -103,6 +115,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ShowPlan /// Edge properties to be shown in the tooltip. /// /// - public List Properties { get; set; } + public List Properties { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/ShowPlan/ShowPlanGraphUtils.cs b/src/Microsoft.SqlTools.ServiceLayer/ShowPlan/ShowPlanGraphUtils.cs index 7d7c99d4..dac156f8 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ShowPlan/ShowPlanGraphUtils.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ShowPlan/ShowPlanGraphUtils.cs @@ -50,19 +50,37 @@ namespace Microsoft.SqlTools.ServiceLayer.ShowPlan }; } - private static List GetProperties(PropertyDescriptorCollection props) + private static List GetProperties(PropertyDescriptorCollection props) { - List propsList = new List(); + List propsList = new List(); foreach (PropertyValue prop in props) { - propsList.Add(new ExecutionPlanGraphElementProperties() + var complexProperty = prop.Value as ExpandableObjectWrapper; + if (complexProperty == null) { - Name = prop.DisplayName, - FormattedValue = prop.DisplayValue, - ShowInTooltip = prop.IsBrowsable, - DisplayOrder = prop.DisplayOrder, - IsLongString = prop.IsLongString - }); + var propertyValue = prop.DisplayValue; + propsList.Add(new ExecutionPlanGraphProperty() + { + Name = prop.DisplayName, + Value = propertyValue, + ShowInTooltip = prop.IsBrowsable, + DisplayOrder = prop.DisplayOrder, + IsLongString = prop.IsLongString, + }); + } + else + { + var propertyValue = GetProperties(complexProperty.Properties); + propsList.Add(new NestedExecutionPlanGraphProperty() + { + Name = prop.DisplayName, + Value = propertyValue, + ShowInTooltip = prop.IsBrowsable, + DisplayOrder = prop.DisplayOrder, + IsLongString = prop.IsLongString, + }); + } + } return propsList; } diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ShowPlan/ShowPlanTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ShowPlan/ShowPlanTests.cs index 7f18b255..197271ea 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ShowPlan/ShowPlanTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ShowPlan/ShowPlanTests.cs @@ -1,3 +1,4 @@ +using System; // // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. @@ -13,17 +14,40 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ShowPlan { public class ShowPlanXMLTests { - [Test] - public void ParseXMLFileReturnsValidShowPlanGraph() + private string queryPlanFileText; + + [SetUp] + public void LoadQueryPlanBeforeEachTest() { Assembly assembly = Assembly.GetAssembly(typeof(ShowPlanXMLTests)); Stream scriptStream = assembly.GetManifestResourceStream(assembly.GetName().Name + ".ShowPlan.TestExecutionPlan.xml"); StreamReader reader = new StreamReader(scriptStream); - string text = reader.ReadToEnd(); - var showPlanGraphs = ShowPlanGraphUtils.CreateShowPlanGraph(text); + queryPlanFileText = reader.ReadToEnd(); + } + + [Test] + public void ParseXMLFileReturnsValidShowPlanGraph() + { + + var showPlanGraphs = ShowPlanGraphUtils.CreateShowPlanGraph(queryPlanFileText); Assert.AreEqual(1, showPlanGraphs.Count, "exactly one show plan graph should be returned"); Assert.NotNull(showPlanGraphs[0], "graph should not be null"); Assert.NotNull(showPlanGraphs[0].Root, "graph should have a root"); } + + [Test] + public void ParsingNestedProperties() + { + string[] commonNestedPropertiesNames = { "MemoryGrantInfo", "OptimizerHardwareDependentProperties" }; + var showPlanGraphs = ShowPlanGraphUtils.CreateShowPlanGraph(queryPlanFileText); + ExecutionPlanNode rootNode = showPlanGraphs[0].Root; + rootNode.Properties.ForEach(p => + { + if (Array.FindIndex(commonNestedPropertiesNames, i => i.Equals(p.Name)) != -1 && (NestedExecutionPlanGraphProperty)p != null) + { + Assert.NotZero(((NestedExecutionPlanGraphProperty)p).Value.Count); + } + }); + } } } \ No newline at end of file