From 007e852f1aead6b904320d915d0871fd3c754c57 Mon Sep 17 00:00:00 2001 From: Jordan Hays <58005768+nofield@users.noreply.github.com> Date: Thu, 11 Aug 2022 10:46:14 -0700 Subject: [PATCH] Add modifiable sort priority to OE nodes (#1627) * modifiable sort priority, dropped ledger folders sorted to the bottom * reorganizing dropped table and view objects in OE integration test * update to Int32 --- .../Nodes/NodeObservableCollection.cs | 30 ++++++------ .../ObjectExplorer/Nodes/TreeNode.cs | 25 ++++------ .../ObjectExplorer/SmoModel/SmoTreeNodes.cs | 4 +- .../ObjectExplorer/SmoModel/SmoTreeNodes.tt | 18 ++++++-- .../SmoModel/SmoTreeNodesDefinition.xml | 4 +- .../Baselines/AllSqlObjects.txt | 46 +++++++++---------- 6 files changed, 66 insertions(+), 61 deletions(-) diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeObservableCollection.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeObservableCollection.cs index 735ecffe..d7e90f73 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeObservableCollection.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeObservableCollection.cs @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -11,8 +11,8 @@ using System.Linq; namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes { - /// - /// A collection class for + /// + /// A collection class for /// public sealed class NodeObservableCollection : ObservableCollection { @@ -30,13 +30,17 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes get { return numInits.HasValue && numInits != 0; } } - public bool IsSorted - { - get - { - // SMO objects are already sorted so no need to sort them again - return this.FirstOrDefault() is SmoTreeNode; - } + public bool IsSorted + { + get + { + // SMO objects are already sorted so no need to sort them again, unless they have dropped folders + bool anyDroppedFolders = this.Any( + node => node is FolderNode && + (node.NodeTypeId == NodeTypes.DroppedLedgerTables || + node.NodeTypeId == NodeTypes.DroppedLedgerViews)); + return this.FirstOrDefault() is SmoTreeNode && !anyDroppedFolders; + } } public void BeginInit() @@ -64,9 +68,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes { try { - if (!IsSorted) - { - DoSort(); + if (!IsSorted) + { + DoSort(); } if (deferredChildren != null) diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs index 9a371628..54f98e2a 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs @@ -413,23 +413,16 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes return CompareSamePriorities(this, other); } - if (this.SortPriority.HasValue && - !other.SortPriority.HasValue) - { - return -1; // this is above other - } - if (!this.SortPriority.HasValue) - { - return 1; // this is below other - } + // Higher SortPriority = lower in the list. A couple nodes are defined with SortPriority of Int16.MaxValue + // so they're placed at the bottom of the node list (Dropped Ledger Tables and Dropped Ledger Views folders) + // Individual objects, like tables and views, don't have a SortPriority defined, so their values need + // to be resolved. If a node doesn't have a SortPriority, set it to the second-highest value. + int thisPriority = this.SortPriority ?? Int32.MaxValue - 1; + int otherPriority = other.SortPriority ?? Int32.MaxValue - 1; - // Both have sort priority - int priDiff = this.SortPriority.Value - other.SortPriority.Value; - if (priDiff < 0) - return -1; // this is below other - if (priDiff == 0) - return 0; - return 1; + // diff > 0 == this below other + // diff < 0 == other below this + return thisPriority - otherPriority; } } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNodes.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNodes.cs index 10799099..8c1270bc 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNodes.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNodes.cs @@ -858,7 +858,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel NodeTypeId = NodeTypes.DroppedLedgerTables, IsSystemObject = false, ValidFor = ValidForFlag.Sql2022|ValidForFlag.AzureV12, - SortPriority = SmoTreeNode.NextSortPriority, + SortPriority = Int32.MaxValue, }); } @@ -922,7 +922,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel NodeTypeId = NodeTypes.DroppedLedgerViews, IsSystemObject = false, IsMsShippedOwned = true, - SortPriority = SmoTreeNode.NextSortPriority, + SortPriority = Int32.MaxValue, }); } diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNodes.tt b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNodes.tt index 920dfdcc..051243d8 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNodes.tt +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNodes.tt @@ -241,7 +241,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel WriteLine(" {"); foreach (var child in children) { - XmlElement childAsXmlElement = GetNodeElement(xmlFile, child.GetAttribute("Name")); + var childName = child.GetAttribute("Name"); + + XmlElement childAsXmlElement = GetNodeElement(xmlFile, childName); if (childAsXmlElement == null) { // TODO SHould we error with clear message that this needs to be fixed? @@ -251,16 +253,22 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel var msShippedOwned = childAsXmlElement.GetAttributeNode("IsMsShippedOwned"); var validFor = childAsXmlElement.GetAttribute("ValidFor"); - if (TreeNodeExists(xmlFile, child.GetAttribute("Name") + "TreeNode")) + var sortPriority = childAsXmlElement.GetAttribute("SortPriority"); + if (sortPriority == string.Empty) { - WriteLine(" currentChildren.Add(new {0}TreeNode {{ SortPriority = SmoTreeNode.NextSortPriority }} );", child.GetAttribute("Name")); + sortPriority = "SmoTreeNode.NextSortPriority"; + } + + if (TreeNodeExists(xmlFile, childName + "TreeNode")) + { + WriteLine(" currentChildren.Add(new {0}TreeNode {{ SortPriority = {1} }} );", childName, sortPriority); } else { WriteLine(" currentChildren.Add(new FolderNode {"); WriteLine(" NodeValue = {0},", childAsXmlElement.GetAttribute("LocLabel")); WriteLine(" NodeType = \"{0}\",", "Folder"); - WriteLine(" NodeTypeId = NodeTypes.{0},", child.GetAttribute("Name")); + WriteLine(" NodeTypeId = NodeTypes.{0},", childName); WriteLine(" IsSystemObject = {0},", child.GetAttribute("IsSystemObject") == "1" ? "true" : "false"); if (msShippedOwned != null) @@ -271,7 +279,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { WriteLine(" ValidFor = {0},", GetValidForFlags(validFor)); } - WriteLine(" SortPriority = SmoTreeNode.NextSortPriority,"); + WriteLine(" SortPriority = {0},", sortPriority); WriteLine(" });"); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNodesDefinition.xml b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNodesDefinition.xml index b7b89992..56f25eb4 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNodesDefinition.xml +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNodesDefinition.xml @@ -165,7 +165,7 @@ - + @@ -251,7 +251,7 @@ - + diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/Baselines/AllSqlObjects.txt b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/Baselines/AllSqlObjects.txt index 0597bd0f..de1fc18b 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/Baselines/AllSqlObjects.txt +++ b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/Baselines/AllSqlObjects.txt @@ -1,21 +1,3 @@ -NodeType: Table Label: HumanResources.MSSQL_DroppedLedgerTable_Ledger_For_Drop_<> (Updatable Ledger) SubType:Ledger Status: -NodeType: Column Label: BusinessEntityID (int, not null) SubType: Status: -NodeType: Column Label: NationalIDNumber (nvarchar(15), not null) SubType: Status: -NodeType: Column Label: LoginID (nvarchar(256), not null) SubType: Status: -NodeType: Column Label: OrganizationNode (hierarchyid, null) SubType: Status: -NodeType: Column Label: ledger_start_transaction_id (bigint, not null) SubType: Status: -NodeType: Column Label: ledger_end_transaction_id (bigint, null) SubType: Status: -NodeType: Column Label: ledger_start_sequence_number (bigint, not null) SubType: Status: -NodeType: Column Label: ledger_end_sequence_number (bigint, null) SubType: Status: -NodeType: HistoryTable Label: HumanResources.MSSQL_DroppedLedgerHistory_Ledger_For_Drop_History_<> (History) SubType:LedgerHistory Status: -NodeType: Column Label: BusinessEntityID (int, not null) SubType: Status: -NodeType: Column Label: NationalIDNumber (nvarchar(15), not null) SubType: Status: -NodeType: Column Label: LoginID (nvarchar(256), not null) SubType: Status: -NodeType: Column Label: OrganizationNode (hierarchyid, null) SubType: Status: -NodeType: Column Label: ledger_start_transaction_id (bigint, not null) SubType: Status: -NodeType: Column Label: ledger_end_transaction_id (bigint, null) SubType: Status: -NodeType: Column Label: ledger_start_sequence_number (bigint, not null) SubType: Status: -NodeType: Column Label: ledger_end_sequence_number (bigint, null) SubType: Status: NodeType: Table Label: dbo.tableWithAllDataTypes SubType: Status: NodeType: Column Label: cDecimal (decimal(18,5), null) SubType: Status: NodeType: Column Label: cNumeric (numeric(18,2), null) SubType: Status: @@ -178,15 +160,24 @@ NodeType: Constraint Label: DF_Person_ModifiedDate SubType: Status: NodeType: Trigger Label: TableTrigger SubType: Status: NodeType: Index Label: PK_Person_BusinessEntityID (Unique, Clustered) SubType:PrimaryKey Status: NodeType: Statistic Label: PK_Person_BusinessEntityID SubType: Status: -NodeType: View Label: HumanResources.MSSQL_DroppedLedgerView_Ledger_For_Drop_Ledger_<> (Ledger) SubType:Ledger Status: +NodeType: Table Label: HumanResources.MSSQL_DroppedLedgerTable_Ledger_For_Drop_<> (Updatable Ledger) SubType:Ledger Status: NodeType: Column Label: BusinessEntityID (int, not null) SubType: Status: NodeType: Column Label: NationalIDNumber (nvarchar(15), not null) SubType: Status: NodeType: Column Label: LoginID (nvarchar(256), not null) SubType: Status: NodeType: Column Label: OrganizationNode (hierarchyid, null) SubType: Status: -NodeType: Column Label: ledger_transaction_id (bigint, null) SubType: Status: -NodeType: Column Label: ledger_sequence_number (bigint, null) SubType: Status: -NodeType: Column Label: ledger_operation_type (int, not null) SubType: Status: -NodeType: Column Label: ledger_operation_type_desc (nvarchar(6), not null) SubType: Status: +NodeType: Column Label: ledger_start_transaction_id (bigint, not null) SubType: Status: +NodeType: Column Label: ledger_end_transaction_id (bigint, null) SubType: Status: +NodeType: Column Label: ledger_start_sequence_number (bigint, not null) SubType: Status: +NodeType: Column Label: ledger_end_sequence_number (bigint, null) SubType: Status: +NodeType: HistoryTable Label: HumanResources.MSSQL_DroppedLedgerHistory_Ledger_For_Drop_History_<> (History) SubType:LedgerHistory Status: +NodeType: Column Label: BusinessEntityID (int, not null) SubType: Status: +NodeType: Column Label: NationalIDNumber (nvarchar(15), not null) SubType: Status: +NodeType: Column Label: LoginID (nvarchar(256), not null) SubType: Status: +NodeType: Column Label: OrganizationNode (hierarchyid, null) SubType: Status: +NodeType: Column Label: ledger_start_transaction_id (bigint, not null) SubType: Status: +NodeType: Column Label: ledger_end_transaction_id (bigint, null) SubType: Status: +NodeType: Column Label: ledger_start_sequence_number (bigint, not null) SubType: Status: +NodeType: Column Label: ledger_end_sequence_number (bigint, null) SubType: Status: NodeType: View Label: HumanResources.Employee_Ledger_AppendOnly_Ledger (Ledger) SubType:Ledger Status: NodeType: Column Label: BusinessEntityID (int, not null) SubType: Status: NodeType: Column Label: NationalIDNumber (nvarchar(15), not null) SubType: Status: @@ -235,6 +226,15 @@ NodeType: Column Label: Suffix (nvarchar(10), null) SubType: Status: NodeType: Column Label: JobTitle (nvarchar(50), not null) SubType: Status: NodeType: Column Label: AdditionalContactInfo (AdditionalContactInfoSchemaCollection, null) SubType: Status: NodeType: Trigger Label: ViewTrigger SubType: Status: +NodeType: View Label: HumanResources.MSSQL_DroppedLedgerView_Ledger_For_Drop_Ledger_<> (Ledger) SubType:Ledger Status: +NodeType: Column Label: BusinessEntityID (int, not null) SubType: Status: +NodeType: Column Label: NationalIDNumber (nvarchar(15), not null) SubType: Status: +NodeType: Column Label: LoginID (nvarchar(256), not null) SubType: Status: +NodeType: Column Label: OrganizationNode (hierarchyid, null) SubType: Status: +NodeType: Column Label: ledger_transaction_id (bigint, null) SubType: Status: +NodeType: Column Label: ledger_sequence_number (bigint, null) SubType: Status: +NodeType: Column Label: ledger_operation_type (int, not null) SubType: Status: +NodeType: Column Label: ledger_operation_type_desc (nvarchar(6), not null) SubType: Status: NodeType: Synonym Label: dbo.MyProduct SubType: Status: NodeType: StoredProcedure Label: dbo.uspGetList SubType: Status: NodeType: StoredProcedureParameter Label: @Product (varchar, Input, No default) SubType:Input Status: