Adding schema based object folders in OE (#1849)

* Making node types automated

* Adding schema based OE

* added folder types in NodeTypes

* Fixing stuff

* Moving schema to parent and cleaning up some code

* Replacing strings with nameof

* Sorting nodetypes generated by tt

* Adding option to put folders after nodes

* Fixing folder and children order

* Fixing tests

* Formatting file

* Formatting tt files

* Fixing tt

* fixing types

* Update src/Microsoft.SqlTools.ServiceLayer/SqlContext/ObjectExplorerSettings.cs

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

* Fixing stuff

* Updating schema definitions and adding more logs

* Fixing copyright

* Adding Integration and Unit Tests

* Fixing test

---------

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
This commit is contained in:
Aasim Khan
2023-02-14 13:40:51 -08:00
committed by GitHub
parent c32e1f2b26
commit c26a2aea14
18 changed files with 2068 additions and 1223 deletions

View File

@@ -71,5 +71,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
// TODO Consider whether Remove operations need to be supported
//public abstract bool CanRemoveChild(TreeNode parent, object context);
//public abstract int GetChildIndexToRemove(TreeNode parent, object context);
/// <summary>
/// A flag that puts child folders after nodes when the node is expanded.
/// </summary>
/// <value></value>
public virtual bool PutFoldersAfterNodes => false;
}
}

View File

@@ -3,11 +3,9 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Linq;
using System.Text;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
@@ -44,7 +42,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
string andPrefix = filter.Length == 0 ? string.Empty : " and ";
var filterString = value.ToPropertyFilterString(type, validForFlag);
if (filterString != string.Empty) {
if (filterString != string.Empty)
{
filter.Append($"{andPrefix}{filterString}");
}
}
@@ -55,5 +54,25 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
}
return string.Empty;
}
/// <summary>
/// Appends a list of property filters to an URN query string
/// </summary>
public static string AddPropertyFilterToFilterString(string filterString, IEnumerable<INodeFilter> filters, Type type, ValidForFlag validForFlag)
{
if (string.IsNullOrEmpty(filterString))
{
return GetPropertyFilter(filters, type, validForFlag);
}
foreach (var value in filters ?? Enumerable.Empty<INodeFilter>())
{
var filter = value.ToPropertyFilterString(type, validForFlag);
if (filter != string.Empty)
{
filterString = filterString.Remove(filterString.Length - 1, 1) + $" and {filter}" + "]";
}
}
return filterString;
}
}
}

View File

@@ -1,147 +1,142 @@
//
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
// This file was generated by a T4 Template. Do not modify directly, instead update the SmoTreeNodesDefinition.xml file
// and re-run the T4 template. This can be done in Visual Studio by right-click in and choosing "Run Custom Tool",
// or from the command-line on any platform by running "build.cmd -Target=CodeGen" or "build.sh -Target=CodeGen"
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// Enum listing possible node types in the object explorer tree
/// </summary>
// TODO Consider replacing this with an auto-gen'd version
public enum NodeTypes
{
None,
SqlServersRoot,
Database,
Server,
ScalarValuedFunction,
TableValuedFunction,
AggregateFunction,
FileGroup,
StoredProcedure,
UserDefinedTableType,
View,
Table,
HistoryTable,
Folder,
Databases,
ExternalResources,
ServerLevelSecurity,
ServerLevelServerObjects,
ServerLevelManagement,
SystemDatabases,
ServerLevelLinkedServerLogins,
ServerLevelServerAudits,
ServerLevelCryptographicProviders,
ServerLevelCredentials,
ServerLevelServerRoles,
ServerLevelLogins,
ServerLevelEventSessions,
ServerLevelServerAuditSpecifications,
ServerLevelEventNotifications,
ServerLevelErrorMessages,
ServerLevelServerTriggers,
ServerLevelLinkedServers,
ServerLevelEndpoints,
SystemScalarValuedFunctions,
SystemTableValuedFunctions,
SystemFunctions,
DacInstancesFolder,
Tables,
Views,
Synonyms,
Programmability,
ServiceBroker,
Storage,
Security,
SystemTables,
FileTables,
SystemViews,
StoredProcedures,
Functions,
ExtendedStoredProcedures,
DatabaseTriggers,
Defaults,
Rules,
Types,
Assemblies,
MessageTypes,
Contracts,
Queues,
Services,
Routes,
DatabaseAndQueueEventNotifications,
RemoteServiceBindings,
BrokerPriorities,
FileGroups,
FullTextCatalogs,
FullTextStopLists,
SqlLogFiles,
PartitionFunctions,
PartitionSchemes,
SearchPropertyLists,
Users,
Roles,
Schemas,
AsymmetricKeys,
Certificates,
SymmetricKeys,
DatabaseEncryptionKeys,
MasterKeys,
Signatures,
DatabaseAuditSpecifications,
Columns,
Keys,
Constraints,
Triggers,
Indexes,
Statistics,
TableValuedFunctions,
ScalarValuedFunctions,
AggregateFunctions,
SystemDataTypes,
UserDefinedDataTypes,
UserDefinedTableTypes,
UserDefinedTypes,
XmlSchemaCollections,
SystemExactNumerics,
SystemApproximateNumerics,
SystemDateAndTimes,
SystemCharacterStrings,
SystemUnicodeCharacterStrings,
SystemBinaryStrings,
SystemOtherDataTypes,
SystemClrDataTypes,
SystemSpatialDataTypes,
UserDefinedTableTypeColumns,
UserDefinedTableTypeKeys,
UserDefinedTableTypeConstraints,
SystemStoredProcedures,
StoredProcedureParameters,
TableValuedFunctionParameters,
ScalarValuedFunctionParameters,
AggregateFunctionParameters,
DatabaseRoles,
ApplicationRoles,
FileGroupFiles,
SystemMessageTypes,
SystemContracts,
SystemServices,
SystemQueues,
Sequences,
SecurityPolicies,
DatabaseScopedCredentials,
ExternalTables,
ExternalResource,
ExternalDataSources,
ExternalFileFormats,
ExternalTable,
AggregateFunctions,
AlwaysEncryptedKeys,
ColumnMasterKeys,
ApplicationRoles,
Assemblies,
AsymmetricKeys,
BrokerPriorities,
Certificates,
ColumnEncryptionKeys,
ColumnMasterKeys,
Columns,
Constraints,
Contracts,
Database,
DatabaseAndQueueEventNotifications,
DatabaseAuditSpecifications,
DatabaseEncryptionKeys,
DatabaseRoles,
Databases,
DatabaseScopedCredentials,
DatabaseTriggers,
DroppedLedgerColumns,
DroppedLedgerTables,
DroppedLedgerViews,
DroppedLedgerColumns,
ExpandableSchema,
ExpandableSchemaProgrammability,
ExternalDataSources,
ExternalFileFormats,
ExternalResource,
ExternalResources,
ExternalTable,
ExternalTables,
FileGroup,
FileGroupFiles,
FileGroups,
Folder,
FullTextCatalogs,
FullTextStopLists,
Functions,
HistoryTable,
Indexes,
Keys,
MasterKeys,
MessageTypes,
PartitionFunctions,
PartitionSchemes,
Programmability,
Queues,
RemoteServiceBindings,
Roles,
ScalarValuedFunction,
ScalarValuedFunctionParameters,
ScalarValuedFunctions,
Schemas,
SearchPropertyLists,
Security,
SecurityPolicies,
Sequences,
Server,
ServerLevelCredentials,
ServerLevelCryptographicProviders,
ServerLevelEndpoints,
ServerLevelErrorMessages,
ServerLevelLinkedServerLogins,
ServerLevelLinkedServers,
ServerLevelLogins,
ServerLevelSecurity,
ServerLevelServerAudits,
ServerLevelServerAuditSpecifications,
ServerLevelServerObjects,
ServerLevelServerRoles,
ServerLevelServerTriggers,
ServiceBroker,
Services,
Signatures,
SqlLogFiles,
Statistics,
Storage,
StoredProcedure,
StoredProcedureParameters,
StoredProcedures,
SymmetricKeys,
Synonyms,
SystemApproximateNumerics,
SystemBinaryStrings,
SystemCharacterStrings,
SystemClrDataTypes,
SystemContracts,
SystemDatabases,
SystemDataTypes,
SystemDateAndTimes,
SystemExactNumerics,
SystemFunctions,
SystemMessageTypes,
SystemOtherDataTypes,
SystemQueues,
SystemScalarValuedFunctions,
SystemServices,
SystemSpatialDataTypes,
SystemStoredProcedures,
SystemTables,
SystemTableValuedFunctions,
SystemUnicodeCharacterStrings,
SystemViews,
Table,
Tables,
TableValuedFunction,
TableValuedFunctionParameters,
TableValuedFunctions,
Triggers,
Types,
UserDefinedDataTypes,
UserDefinedTableType,
UserDefinedTableTypeColumns,
UserDefinedTableTypeConstraints,
UserDefinedTableTypeKeys,
UserDefinedTableTypes,
UserDefinedTypes,
Users,
View,
Views,
XmlSchemaCollections,
}
}

View File

@@ -0,0 +1,117 @@
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Xml.dll" #>
<#@ assembly name="System.Core.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Globalization" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq"#>
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
// This file was generated by a T4 Template. Do not modify directly, instead update the SmoTreeNodesDefinition.xml file
// and re-run the T4 template. This can be done in Visual Studio by right-click in and choosing "Run Custom Tool",
// or from the command-line on any platform by running "build.cmd -Target=CodeGen" or "build.sh -Target=CodeGen"
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// Enum listing possible node types in the object explorer tree
/// </summary>
public enum NodeTypes
{
<#
var directory = Path.GetDirectoryName(Host.TemplateFile);
string xmlFile = Path.Combine(directory, "..\\SmoModel\\SmoTreeNodesDefinition.xml");
var allTreeNodes = GetUniqueNodeTypes(xmlFile);
foreach (var name in allTreeNodes)
{
WriteLine(" {0},", name);
}
#>
}
}
<#+
public static List<string> GetUniqueNodeTypes(string xmlFile)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
// Adding all node types
HashSet<string> retElements = new HashSet<string>();
XmlNodeList nodeList = doc.SelectNodes("/ServerExplorerTree/Node");
foreach (XmlElement item in nodeList)
{
retElements.Add(item.GetAttribute("Name"));
foreach (XmlElement child in GetChildren(xmlFile, item.GetAttribute("Name")))
{
retElements.Add(child.GetAttribute("Name"));
}
}
// Adding UniqueTreeNodes
foreach(var name in GetUniqueTreeNodes(xmlFile))
{
retElements.Add(name);
}
// Adding types that are not present anywhere. These types are referred in tests.
retElements.Add("Folder");
var retList = retElements.ToList();
retList.Sort();
return retList;
}
public static List<XmlElement> GetChildren(string xmlFile, string parentName)
{
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes(string.Format("/ServerExplorerTree/Node[@Name='{0}']/Child", parentName));
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
public static XmlElement GetNodeElement(string xmlFile, string nodeName)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
return (XmlElement)doc.SelectSingleNode(string.Format("/ServerExplorerTree/Node[@Name='{0}']", nodeName));
}
public static List<string> GetUniqueTreeNodes(string xmlFile)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<string> retElements = new List<string>();
XmlNodeList nodeList = doc.SelectNodes("/ServerExplorerTree/CodeGenOptions/UniqueTreeNode");
foreach (XmlElement item in nodeList)
{
retElements.Add(item.GetAttribute("Name").Replace("TreeNode", string.Empty));
}
return retElements;
}
#>

View File

@@ -6,6 +6,7 @@
#nullable disable
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
@@ -14,6 +15,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
/// </summary>
public class FolderNode : SmoTreeNode
{
public FolderNode()
{
this.NodeType = nameof(NodeTypes.Folder);
}
/// <summary>
/// For folders, this copies the context of its parent if available
/// </summary>

View File

@@ -125,7 +125,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
else
{
var returnSet = new HashSet<string>();
if (currentNode.ContainedType() == "Database")
if (currentNode.ContainedType() == "Database" || currentNode.ContainedType() == "ExpandableSchema")
{
path = databaseName + "/" + path;
}

View File

@@ -31,14 +31,24 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
try
{
OnExpandPopulateFoldersAndFilter(allChildren, parent, includeSystemObjects);
RemoveFoldersFromInvalidSqlServerVersions(allChildren, parent);
OnExpandPopulateNonFolders(allChildren, parent, refresh, name, cancellationToken);
if (this.PutFoldersAfterNodes)
{
OnExpandPopulateNonFolders(allChildren, parent, refresh, name, cancellationToken);
OnExpandPopulateFoldersAndFilter(allChildren, parent, includeSystemObjects);
RemoveFoldersFromInvalidSqlServerVersions(allChildren, parent);
}
else
{
OnExpandPopulateFoldersAndFilter(allChildren, parent, includeSystemObjects);
RemoveFoldersFromInvalidSqlServerVersions(allChildren, parent);
OnExpandPopulateNonFolders(allChildren, parent, refresh, name, cancellationToken);
}
OnBeginAsyncOperations(parent);
}
catch(Exception ex)
catch (Exception ex)
{
string error = string.Format(CultureInfo.InvariantCulture, "Failed expanding oe children. parent:{0} error:{1} inner:{2} stacktrace:{3}",
string error = string.Format(CultureInfo.InvariantCulture, "Failed expanding oe children. parent:{0} error:{1} inner:{2} stacktrace:{3}",
parent != null ? parent.GetNodePath() : "", ex.Message, ex.InnerException != null ? ex.InnerException.Message : "", ex.StackTrace);
Logger.Write(TraceEventType.Error, error);
throw;

View File

@@ -15,6 +15,7 @@ using System.Composition;
using System.Linq;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Broker;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.Utility;
using Index = Microsoft.SqlServer.Management.Smo.Index;
@@ -34,6 +35,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Server parentServer = context.Parent as Server;
if (parentServer != null)
{
Logger.Verbose("Parent of type `Server` found");
var retValue = parentServer.Databases;
if (retValue != null)
{
@@ -60,6 +62,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Server parentServer = context.Parent as Server;
if (parentServer != null)
{
Logger.Verbose("Parent of type `Server` found");
var retValue = parentServer.LinkedServers;
if (retValue != null)
{
@@ -86,6 +89,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Server parentServer = context.Parent as Server;
if (parentServer != null)
{
Logger.Verbose("Parent of type `Server` found");
var retValue = parentServer.Logins;
if (retValue != null)
{
@@ -112,6 +116,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Server parentServer = context.Parent as Server;
if (parentServer != null)
{
Logger.Verbose("Parent of type `Server` found");
var retValue = parentServer.Roles;
if (retValue != null)
{
@@ -138,6 +143,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Server parentServer = context.Parent as Server;
if (parentServer != null)
{
Logger.Verbose("Parent of type `Server` found");
var retValue = parentServer.Credentials;
if (retValue != null)
{
@@ -164,6 +170,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Server parentServer = context.Parent as Server;
if (parentServer != null)
{
Logger.Verbose("Parent of type `Server` found");
var retValue = parentServer.CryptographicProviders;
if (retValue != null)
{
@@ -190,6 +197,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Server parentServer = context.Parent as Server;
if (parentServer != null)
{
Logger.Verbose("Parent of type `Server` found");
var retValue = parentServer.Audits;
if (retValue != null)
{
@@ -216,6 +224,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Server parentServer = context.Parent as Server;
if (parentServer != null)
{
Logger.Verbose("Parent of type `Server` found");
var retValue = parentServer.ServerAuditSpecifications;
if (retValue != null)
{
@@ -242,6 +251,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Server parentServer = context.Parent as Server;
if (parentServer != null)
{
Logger.Verbose("Parent of type `Server` found");
var retValue = parentServer.Endpoints;
if (retValue != null)
{
@@ -268,6 +278,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Server parentServer = context.Parent as Server;
if (parentServer != null)
{
Logger.Verbose("Parent of type `Server` found");
var retValue = parentServer.LinkedServers;
if (retValue != null)
{
@@ -297,6 +308,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Server parentServer = context.Parent as Server;
if (parentServer != null)
{
Logger.Verbose("Parent of type `Server` found");
var retValue = parentServer.Triggers;
if (retValue != null)
{
@@ -323,6 +335,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Server parentServer = context.Parent as Server;
if (parentServer != null)
{
Logger.Verbose("Parent of type `Server` found");
var retValue = parentServer.UserDefinedMessages;
if (retValue != null)
{
@@ -349,6 +362,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.Tables;
if (retValue != null)
{
@@ -358,6 +372,28 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return ret;
}
}
Schema parentSchema = context.Parent as Schema;
if (parentSchema != null)
{
Logger.Verbose("Parent of type `Schema` found");
List<NodePropertyFilter> filters = new List<NodePropertyFilter>();
filters.Add(new NodePropertyFilter()
{
Property = nameof(Schema),
Type = typeof(string),
Values = new List<object> { parentSchema.Name },
ValidFor = ValidForFlag.All
});
filter = INodeFilter.AddPropertyFilterToFilterString(filter, filters, this.GetType(), context.ValidFor);
var retValue = parentSchema.Parent.Tables;
if (retValue != null)
{
retValue.ClearAndInitialize(filter, extraProperties);
var ret = new SmoCollectionWrapper<Table>(retValue).Where(c => PassesFinalFilters(parentSchema, c));
Logger.Verbose("End query Table");
return ret;
}
}
return Enumerable.Empty<SqlSmoObject>();
}
}
@@ -375,6 +411,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Table parentTable = context.Parent as Table;
if (parentTable != null)
{
Logger.Verbose("Parent of type `Table` found");
var retValue = parentTable.Parent.Tables;
if (retValue != null)
{
@@ -401,6 +438,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.Views;
if (retValue != null)
{
@@ -410,6 +448,28 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return ret;
}
}
Schema parentSchema = context.Parent as Schema;
if (parentSchema != null)
{
Logger.Verbose("Parent of type `Schema` found");
List<NodePropertyFilter> filters = new List<NodePropertyFilter>();
filters.Add(new NodePropertyFilter()
{
Property = nameof(Schema),
Type = typeof(string),
Values = new List<object> { parentSchema.Name },
ValidFor = ValidForFlag.All
});
filter = INodeFilter.AddPropertyFilterToFilterString(filter, filters, this.GetType(), context.ValidFor);
var retValue = parentSchema.Parent.Views;
if (retValue != null)
{
retValue.ClearAndInitialize(filter, extraProperties);
var ret = new SmoCollectionWrapper<View>(retValue).Where(c => PassesFinalFilters(parentSchema, c));
Logger.Verbose("End query View");
return ret;
}
}
return Enumerable.Empty<SqlSmoObject>();
}
}
@@ -430,6 +490,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.Synonyms;
if (retValue != null)
{
@@ -439,6 +500,28 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return ret;
}
}
Schema parentSchema = context.Parent as Schema;
if (parentSchema != null)
{
Logger.Verbose("Parent of type `Schema` found");
List<NodePropertyFilter> filters = new List<NodePropertyFilter>();
filters.Add(new NodePropertyFilter()
{
Property = nameof(Schema),
Type = typeof(string),
Values = new List<object> { parentSchema.Name },
ValidFor = ValidForFlag.All
});
filter = INodeFilter.AddPropertyFilterToFilterString(filter, filters, this.GetType(), context.ValidFor);
var retValue = parentSchema.Parent.Synonyms;
if (retValue != null)
{
retValue.ClearAndInitialize(filter, extraProperties);
var ret = new SmoCollectionWrapper<Synonym>(retValue).Where(c => PassesFinalFilters(parentSchema, c));
Logger.Verbose("End query Synonym");
return ret;
}
}
return Enumerable.Empty<SqlSmoObject>();
}
}
@@ -456,6 +539,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
TableViewTableTypeBase parentTableViewTableTypeBase = context.Parent as TableViewTableTypeBase;
if (parentTableViewTableTypeBase != null)
{
Logger.Verbose("Parent of type `TableViewTableTypeBase` found");
var retValue = parentTableViewTableTypeBase.Columns;
if (retValue != null)
{
@@ -482,6 +566,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
TableViewTableTypeBase parentTableViewTableTypeBase = context.Parent as TableViewTableTypeBase;
if (parentTableViewTableTypeBase != null)
{
Logger.Verbose("Parent of type `TableViewTableTypeBase` found");
var retValue = parentTableViewTableTypeBase.Indexes;
if (retValue != null)
{
@@ -508,6 +593,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Table parentTable = context.Parent as Table;
if (parentTable != null)
{
Logger.Verbose("Parent of type `Table` found");
var retValue = parentTable.Checks;
if (retValue != null)
{
@@ -534,6 +620,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Table parentTable = context.Parent as Table;
if (parentTable != null)
{
Logger.Verbose("Parent of type `Table` found");
var retValue = parentTable.ForeignKeys;
if (retValue != null)
{
@@ -560,6 +647,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Table parentTable = context.Parent as Table;
if (parentTable != null)
{
Logger.Verbose("Parent of type `Table` found");
var retValue = parentTable.Columns;
if (retValue != null)
{
@@ -581,6 +669,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
UserDefinedTableType parentUserDefinedTableType = context.Parent as UserDefinedTableType;
if (parentUserDefinedTableType != null)
{
Logger.Verbose("Parent of type `UserDefinedTableType` found");
var retValue = parentUserDefinedTableType.Columns;
if (retValue != null)
{
@@ -619,6 +708,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Table parentTable = context.Parent as Table;
if (parentTable != null)
{
Logger.Verbose("Parent of type `Table` found");
var retValue = parentTable.Triggers;
if (retValue != null)
{
@@ -631,6 +721,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
View parentView = context.Parent as View;
if (parentView != null)
{
Logger.Verbose("Parent of type `View` found");
var retValue = parentView.Triggers;
if (retValue != null)
{
@@ -660,6 +751,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Table parentTable = context.Parent as Table;
if (parentTable != null)
{
Logger.Verbose("Parent of type `Table` found");
var retValue = parentTable.FullTextIndex;
if (retValue != null)
{
@@ -687,6 +779,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
TableViewBase parentTableViewBase = context.Parent as TableViewBase;
if (parentTableViewBase != null)
{
Logger.Verbose("Parent of type `TableViewBase` found");
var retValue = parentTableViewBase.Statistics;
if (retValue != null)
{
@@ -716,6 +809,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.Triggers;
if (retValue != null)
{
@@ -742,6 +836,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.Assemblies;
if (retValue != null)
{
@@ -768,6 +863,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.Sequences;
if (retValue != null)
{
@@ -777,6 +873,28 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return ret;
}
}
Schema parentSchema = context.Parent as Schema;
if (parentSchema != null)
{
Logger.Verbose("Parent of type `Schema` found");
List<NodePropertyFilter> filters = new List<NodePropertyFilter>();
filters.Add(new NodePropertyFilter()
{
Property = nameof(Schema),
Type = typeof(string),
Values = new List<object> { parentSchema.Name },
ValidFor = ValidForFlag.All
});
filter = INodeFilter.AddPropertyFilterToFilterString(filter, filters, this.GetType(), context.ValidFor);
var retValue = parentSchema.Parent.Sequences;
if (retValue != null)
{
retValue.ClearAndInitialize(filter, extraProperties);
var ret = new SmoCollectionWrapper<Sequence>(retValue).Where(c => PassesFinalFilters(parentSchema, c));
Logger.Verbose("End query Sequence");
return ret;
}
}
return Enumerable.Empty<SqlSmoObject>();
}
}
@@ -797,6 +915,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.UserDefinedDataTypes;
if (retValue != null)
{
@@ -806,6 +925,28 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return ret;
}
}
Schema parentSchema = context.Parent as Schema;
if (parentSchema != null)
{
Logger.Verbose("Parent of type `Schema` found");
List<NodePropertyFilter> filters = new List<NodePropertyFilter>();
filters.Add(new NodePropertyFilter()
{
Property = nameof(Schema),
Type = typeof(string),
Values = new List<object> { parentSchema.Name },
ValidFor = ValidForFlag.All
});
filter = INodeFilter.AddPropertyFilterToFilterString(filter, filters, this.GetType(), context.ValidFor);
var retValue = parentSchema.Parent.UserDefinedDataTypes;
if (retValue != null)
{
retValue.ClearAndInitialize(filter, extraProperties);
var ret = new SmoCollectionWrapper<UserDefinedDataType>(retValue).Where(c => PassesFinalFilters(parentSchema, c));
Logger.Verbose("End query UserDefinedDataType");
return ret;
}
}
return Enumerable.Empty<SqlSmoObject>();
}
}
@@ -823,6 +964,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.UserDefinedTableTypes;
if (retValue != null)
{
@@ -832,6 +974,28 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return ret;
}
}
Schema parentSchema = context.Parent as Schema;
if (parentSchema != null)
{
Logger.Verbose("Parent of type `Schema` found");
List<NodePropertyFilter> filters = new List<NodePropertyFilter>();
filters.Add(new NodePropertyFilter()
{
Property = nameof(Schema),
Type = typeof(string),
Values = new List<object> { parentSchema.Name },
ValidFor = ValidForFlag.All
});
filter = INodeFilter.AddPropertyFilterToFilterString(filter, filters, this.GetType(), context.ValidFor);
var retValue = parentSchema.Parent.UserDefinedTableTypes;
if (retValue != null)
{
retValue.ClearAndInitialize(filter, extraProperties);
var ret = new SmoCollectionWrapper<UserDefinedTableType>(retValue).Where(c => PassesFinalFilters(parentSchema, c));
Logger.Verbose("End query UserDefinedTableType");
return ret;
}
}
return Enumerable.Empty<SqlSmoObject>();
}
}
@@ -849,6 +1013,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.XmlSchemaCollections;
if (retValue != null)
{
@@ -858,6 +1023,28 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return ret;
}
}
Schema parentSchema = context.Parent as Schema;
if (parentSchema != null)
{
Logger.Verbose("Parent of type `Schema` found");
List<NodePropertyFilter> filters = new List<NodePropertyFilter>();
filters.Add(new NodePropertyFilter()
{
Property = nameof(Schema),
Type = typeof(string),
Values = new List<object> { parentSchema.Name },
ValidFor = ValidForFlag.All
});
filter = INodeFilter.AddPropertyFilterToFilterString(filter, filters, this.GetType(), context.ValidFor);
var retValue = parentSchema.Parent.XmlSchemaCollections;
if (retValue != null)
{
retValue.ClearAndInitialize(filter, extraProperties);
var ret = new SmoCollectionWrapper<XmlSchemaCollection>(retValue).Where(c => PassesFinalFilters(parentSchema, c));
Logger.Verbose("End query XmlSchemaCollection");
return ret;
}
}
return Enumerable.Empty<SqlSmoObject>();
}
}
@@ -875,6 +1062,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.UserDefinedTypes;
if (retValue != null)
{
@@ -884,6 +1072,28 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return ret;
}
}
Schema parentSchema = context.Parent as Schema;
if (parentSchema != null)
{
Logger.Verbose("Parent of type `Schema` found");
List<NodePropertyFilter> filters = new List<NodePropertyFilter>();
filters.Add(new NodePropertyFilter()
{
Property = nameof(Schema),
Type = typeof(string),
Values = new List<object> { parentSchema.Name },
ValidFor = ValidForFlag.All
});
filter = INodeFilter.AddPropertyFilterToFilterString(filter, filters, this.GetType(), context.ValidFor);
var retValue = parentSchema.Parent.UserDefinedTypes;
if (retValue != null)
{
retValue.ClearAndInitialize(filter, extraProperties);
var ret = new SmoCollectionWrapper<UserDefinedType>(retValue).Where(c => PassesFinalFilters(parentSchema, c));
Logger.Verbose("End query UserDefinedType");
return ret;
}
}
return Enumerable.Empty<SqlSmoObject>();
}
}
@@ -901,6 +1111,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.UserDefinedFunctions;
if (retValue != null)
{
@@ -910,6 +1121,28 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return ret;
}
}
Schema parentSchema = context.Parent as Schema;
if (parentSchema != null)
{
Logger.Verbose("Parent of type `Schema` found");
List<NodePropertyFilter> filters = new List<NodePropertyFilter>();
filters.Add(new NodePropertyFilter()
{
Property = nameof(Schema),
Type = typeof(string),
Values = new List<object> { parentSchema.Name },
ValidFor = ValidForFlag.All
});
filter = INodeFilter.AddPropertyFilterToFilterString(filter, filters, this.GetType(), context.ValidFor);
var retValue = parentSchema.Parent.UserDefinedFunctions;
if (retValue != null)
{
retValue.ClearAndInitialize(filter, extraProperties);
var ret = new SmoCollectionWrapper<UserDefinedFunction>(retValue).Where(c => PassesFinalFilters(parentSchema, c));
Logger.Verbose("End query UserDefinedFunction");
return ret;
}
}
return Enumerable.Empty<SqlSmoObject>();
}
}
@@ -927,6 +1160,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.UserDefinedAggregates;
if (retValue != null)
{
@@ -936,6 +1170,28 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return ret;
}
}
Schema parentSchema = context.Parent as Schema;
if (parentSchema != null)
{
Logger.Verbose("Parent of type `Schema` found");
List<NodePropertyFilter> filters = new List<NodePropertyFilter>();
filters.Add(new NodePropertyFilter()
{
Property = nameof(Schema),
Type = typeof(string),
Values = new List<object> { parentSchema.Name },
ValidFor = ValidForFlag.All
});
filter = INodeFilter.AddPropertyFilterToFilterString(filter, filters, this.GetType(), context.ValidFor);
var retValue = parentSchema.Parent.UserDefinedAggregates;
if (retValue != null)
{
retValue.ClearAndInitialize(filter, extraProperties);
var ret = new SmoCollectionWrapper<UserDefinedAggregate>(retValue).Where(c => PassesFinalFilters(parentSchema, c));
Logger.Verbose("End query UserDefinedAggregate");
return ret;
}
}
return Enumerable.Empty<SqlSmoObject>();
}
}
@@ -953,6 +1209,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.FileGroups;
if (retValue != null)
{
@@ -979,6 +1236,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
FileGroup parentFileGroup = context.Parent as FileGroup;
if (parentFileGroup != null)
{
Logger.Verbose("Parent of type `FileGroup` found");
var retValue = parentFileGroup.Files;
if (retValue != null)
{
@@ -1005,6 +1263,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.FullTextCatalogs;
if (retValue != null)
{
@@ -1031,6 +1290,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.FullTextStopLists;
if (retValue != null)
{
@@ -1057,6 +1317,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.PartitionFunctions;
if (retValue != null)
{
@@ -1083,6 +1344,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.PartitionSchemes;
if (retValue != null)
{
@@ -1109,6 +1371,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.SearchPropertyLists;
if (retValue != null)
{
@@ -1135,6 +1398,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.Users;
if (retValue != null)
{
@@ -1161,6 +1425,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.Schemas;
if (retValue != null)
{
@@ -1187,6 +1452,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.AsymmetricKeys;
if (retValue != null)
{
@@ -1213,6 +1479,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.Certificates;
if (retValue != null)
{
@@ -1239,6 +1506,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.SymmetricKeys;
if (retValue != null)
{
@@ -1265,6 +1533,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.DatabaseEncryptionKey;
if (retValue != null)
{
@@ -1292,6 +1561,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.MasterKey;
if (retValue != null)
{
@@ -1319,6 +1589,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.DatabaseAuditSpecifications;
if (retValue != null)
{
@@ -1345,6 +1616,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.SecurityPolicies;
if (retValue != null)
{
@@ -1371,6 +1643,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.DatabaseScopedCredentials;
if (retValue != null)
{
@@ -1397,6 +1670,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.Roles;
if (retValue != null)
{
@@ -1423,6 +1697,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.ApplicationRoles;
if (retValue != null)
{
@@ -1449,6 +1724,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.ColumnMasterKeys;
if (retValue != null)
{
@@ -1475,6 +1751,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.ColumnEncryptionKeys;
if (retValue != null)
{
@@ -1501,6 +1778,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.ServiceBroker;
if (retValue != null)
{
@@ -1528,6 +1806,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
ServiceBroker parentServiceBroker = context.Parent as ServiceBroker;
if (parentServiceBroker != null)
{
Logger.Verbose("Parent of type `ServiceBroker` found");
var retValue = parentServiceBroker.Services;
if (retValue != null)
{
@@ -1554,6 +1833,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
ServiceBroker parentServiceBroker = context.Parent as ServiceBroker;
if (parentServiceBroker != null)
{
Logger.Verbose("Parent of type `ServiceBroker` found");
var retValue = parentServiceBroker.ServiceContracts;
if (retValue != null)
{
@@ -1580,6 +1860,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
ServiceBroker parentServiceBroker = context.Parent as ServiceBroker;
if (parentServiceBroker != null)
{
Logger.Verbose("Parent of type `ServiceBroker` found");
var retValue = parentServiceBroker.Queues;
if (retValue != null)
{
@@ -1606,6 +1887,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
ServiceBroker parentServiceBroker = context.Parent as ServiceBroker;
if (parentServiceBroker != null)
{
Logger.Verbose("Parent of type `ServiceBroker` found");
var retValue = parentServiceBroker.RemoteServiceBindings;
if (retValue != null)
{
@@ -1632,6 +1914,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
ServiceBroker parentServiceBroker = context.Parent as ServiceBroker;
if (parentServiceBroker != null)
{
Logger.Verbose("Parent of type `ServiceBroker` found");
var retValue = parentServiceBroker.Priorities;
if (retValue != null)
{
@@ -1658,6 +1941,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
ServiceBroker parentServiceBroker = context.Parent as ServiceBroker;
if (parentServiceBroker != null)
{
Logger.Verbose("Parent of type `ServiceBroker` found");
var retValue = parentServiceBroker.MessageTypes;
if (retValue != null)
{
@@ -1684,6 +1968,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.ExternalDataSources;
if (retValue != null)
{
@@ -1710,6 +1995,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.ExternalFileFormats;
if (retValue != null)
{
@@ -1736,6 +2022,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.StoredProcedures;
if (retValue != null)
{
@@ -1745,6 +2032,28 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return ret;
}
}
Schema parentSchema = context.Parent as Schema;
if (parentSchema != null)
{
Logger.Verbose("Parent of type `Schema` found");
List<NodePropertyFilter> filters = new List<NodePropertyFilter>();
filters.Add(new NodePropertyFilter()
{
Property = nameof(Schema),
Type = typeof(string),
Values = new List<object> { parentSchema.Name },
ValidFor = ValidForFlag.All
});
filter = INodeFilter.AddPropertyFilterToFilterString(filter, filters, this.GetType(), context.ValidFor);
var retValue = parentSchema.Parent.StoredProcedures;
if (retValue != null)
{
retValue.ClearAndInitialize(filter, extraProperties);
var ret = new SmoCollectionWrapper<StoredProcedure>(retValue).Where(c => PassesFinalFilters(parentSchema, c));
Logger.Verbose("End query StoredProcedure");
return ret;
}
}
return Enumerable.Empty<SqlSmoObject>();
}
}
@@ -1762,6 +2071,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.ExtendedStoredProcedures;
if (retValue != null)
{
@@ -1788,6 +2098,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
StoredProcedure parentStoredProcedure = context.Parent as StoredProcedure;
if (parentStoredProcedure != null)
{
Logger.Verbose("Parent of type `StoredProcedure` found");
var retValue = parentStoredProcedure.Parameters;
if (retValue != null)
{
@@ -1800,6 +2111,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
UserDefinedAggregate parentUserDefinedAggregate = context.Parent as UserDefinedAggregate;
if (parentUserDefinedAggregate != null)
{
Logger.Verbose("Parent of type `UserDefinedAggregate` found");
var retValue = parentUserDefinedAggregate.Parameters;
if (retValue != null)
{
@@ -1812,6 +2124,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
UserDefinedFunction parentUserDefinedFunction = context.Parent as UserDefinedFunction;
if (parentUserDefinedFunction != null)
{
Logger.Verbose("Parent of type `UserDefinedFunction` found");
var retValue = parentUserDefinedFunction.Parameters;
if (retValue != null)
{
@@ -1838,6 +2151,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
PartitionFunction parentPartitionFunction = context.Parent as PartitionFunction;
if (parentPartitionFunction != null)
{
Logger.Verbose("Parent of type `PartitionFunction` found");
var retValue = parentPartitionFunction.PartitionFunctionParameters;
if (retValue != null)
{
@@ -1864,6 +2178,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
Database parentDatabase = context.Parent as Database;
if (parentDatabase != null)
{
Logger.Verbose("Parent of type `Database` found");
var retValue = parentDatabase.Parent.SystemDataTypes;
if (retValue != null)
{

View File

@@ -24,318 +24,354 @@ using System.Composition;
using System.Linq;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Broker;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.Utility;
using Index = Microsoft.SqlServer.Management.Smo.Index;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
<#
var directory = Path.GetDirectoryName(Host.TemplateFile);
string xmlFile = Path.Combine(directory, "SmoQueryModelDefinition.xml");
var directory = Path.GetDirectoryName(Host.TemplateFile);
string xmlFile = Path.Combine(directory, "SmoQueryModelDefinition.xml");
/////////
// Now generate all the Query methods
/////////
var allNodes = GetNodes(xmlFile);
var indent = " ";
foreach (var nodeName in allNodes)
{
XmlElement nodeElement = GetNodeElement(xmlFile, nodeName);
IList<string> parents = GetParents(nodeElement, xmlFile, nodeName);
string nodeType = GetNodeType(nodeElement, nodeName);
var validFor = nodeElement.GetAttribute("ValidFor");
string queryBaseClass = "SmoQuerier";
PushIndent(indent);
WriteLine("");
WriteLine("[Export(typeof({0}))]", queryBaseClass);
WriteLine("internal partial class {0}Querier: {1}", nodeName, queryBaseClass);
WriteLine("{");
PushIndent(indent);
// Supported Types
WriteLine("Type[] supportedTypes = new Type[] { typeof("+ nodeType + ") };");
if (!string.IsNullOrWhiteSpace(validFor))
/////////
// Now generate all the Query methods
/////////
var allNodes = GetNodes(xmlFile);
var indent = " ";
foreach (var nodeName in allNodes)
{
WriteLine("");
WriteLine("public override ValidForFlag ValidFor {{ get {{ return {0}; }} }}", GetValidForFlags(validFor));
WriteLine("");
}
XmlElement nodeElement = GetNodeElement(xmlFile, nodeName);
IList<string> parents = GetParents(nodeElement, xmlFile, nodeName);
string nodeType = GetNodeType(nodeElement, nodeName);
var validFor = nodeElement.GetAttribute("ValidFor");
WriteLine("");
WriteLine("public override Type[] SupportedObjectTypes { get { return supportedTypes; } }");
WriteLine("");
// Query impl
WriteLine("public override IEnumerable<SqlSmoObject> Query(SmoQueryContext context, string filter, bool refresh, IEnumerable<string> extraProperties)");
WriteLine("{");
PushIndent(indent);
WriteLine("Logger.Verbose(\"Begin query {0}\");", nodeType);
// TODO Allow override of the navigation path
foreach(var parentType in parents)
{
string parentVar = string.Format("parent{0}", parentType);
WriteLine("{0} {1} = context.Parent as {0};", parentType, parentVar);
WriteLine("if ({0} != null)", parentVar);
WriteLine("{");
PushIndent(indent);
XmlElement navPathElement = GetNavPathElement(xmlFile, nodeName, parentType);
string navigationPath = GetNavigationPath(nodeElement, nodeName, navPathElement);
string subField = GetNavPathAttribute(navPathElement, "SubField");
string fieldType = GetNavPathAttribute(navPathElement, "FieldType");
WriteLine("var retValue = {0}.{1};", parentVar, navigationPath);
WriteLine("if (retValue != null)");
WriteLine("{");
PushIndent(indent);
if (IsCollection(nodeElement))
{
WriteLine("retValue.ClearAndInitialize(filter, extraProperties);");
if (string.IsNullOrEmpty(subField) )
{
WriteLine("var ret = new SmoCollectionWrapper<{0}>(retValue).Where(c => PassesFinalFilters({1}, c));", nodeType, parentVar);
WriteLine("Logger.Verbose(\"End query {0}\");", nodeType);
WriteLine("return ret;");
}
else
{
WriteLine("List<{0}> subFieldResult = new List<{0}>();", nodeType);
WriteLine("foreach({0} field in retValue)", fieldType);
WriteLine("{");
PushIndent(indent);
WriteLine("{0} subField = field.{1};", nodeType, subField);
WriteLine("if (subField != null)");
WriteLine("{");
PushIndent(indent);
WriteLine("subFieldResult.Add(subField);");
PopIndent();
WriteLine("}");
PopIndent();
WriteLine("}");
WriteLine("var ret = subFieldResult.Where(c => PassesFinalFilters({1}, c));", nodeType, parentVar);
WriteLine("Logger.Verbose(\"End query {0}\");", nodeType);
WriteLine("return ret;");
}
}
else
{
WriteLine("if (refresh)");
string queryBaseClass = "SmoQuerier";
PushIndent(indent);
WriteLine("");
WriteLine("[Export(typeof({0}))]", queryBaseClass);
WriteLine("internal partial class {0}Querier: {1}", nodeName, queryBaseClass);
WriteLine("{");
PushIndent(indent);
WriteLine("{0}.{1}.Refresh();", parentVar, navigationPath);
// Supported Types
WriteLine("Type[] supportedTypes = new Type[] { typeof("+ nodeType + ") };");
if (!string.IsNullOrWhiteSpace(validFor))
{
WriteLine("");
WriteLine("public override ValidForFlag ValidFor {{ get {{ return {0}; }} }}", GetValidForFlags(validFor));
WriteLine("");
}
WriteLine("");
WriteLine("public override Type[] SupportedObjectTypes { get { return supportedTypes; } }");
WriteLine("");
// Query impl
WriteLine("public override IEnumerable<SqlSmoObject> Query(SmoQueryContext context, string filter, bool refresh, IEnumerable<string> extraProperties)");
WriteLine("{");
PushIndent(indent);
WriteLine("Logger.Verbose(\"Begin query {0}\");", nodeType);
// TODO Allow override of the navigation path
foreach(var parentType in parents)
{
string parentVar = string.Format("parent{0}", parentType);
WriteLine("{0} {1} = context.Parent as {0};", parentType, parentVar);
WriteLine("if ({0} != null)", parentVar);
WriteLine("{");
PushIndent(indent);
WriteLine("Logger.Verbose(\"Parent of type `{0}` found\");",parentType);
XmlElement navPathElement = GetNavPathElement(xmlFile, nodeName, parentType);
string navigationPath = GetNavigationPath(nodeElement, nodeName, navPathElement);
string subField = GetNavPathAttribute(navPathElement, "SubField");
string fieldType = GetNavPathAttribute(navPathElement, "FieldType");
if(navPathElement != null){
/**
Adding runtime filters to the querier based on the property values available in the context.
The code below will go through all the filters in the navPath element and add them to the filter string
recieved by the querier.
**/
XmlNodeList runtimeFilters = navPathElement.GetElementsByTagName("Filter");
if(runtimeFilters.Count > 0)
{
WriteLine("List<NodePropertyFilter> filters = new List<NodePropertyFilter>();");
foreach(XmlElement filter in runtimeFilters)
{
string filterName = filter.GetAttribute("Property");
string filterField = filter.GetAttribute("Field");
string filterType = filter.GetAttribute("Type");
string filterValidFor = filter.GetAttribute("ValidFor");
WriteLine("filters.Add(new NodePropertyFilter()");
WriteLine("{");
PushIndent(indent);
WriteLine("Property = nameof({0}),", filterName);
WriteLine("Type = typeof({0}),", filterType);
WriteLine("Values = new List<object> {{ {0}.{1} }},", parentVar, filterField);
if(!string.IsNullOrWhiteSpace(filterValidFor))
{
WriteLine("ValidFor = {0},", GetValidForFlags(filterValidFor));
}
else
{
WriteLine("ValidFor = ValidForFlag.All ");
}
PopIndent();
WriteLine("});");
}
WriteLine("filter = INodeFilter.AddPropertyFilterToFilterString(filter, filters, this.GetType(), context.ValidFor);");
}
}
WriteLine("var retValue = {0}.{1};", parentVar, navigationPath);
WriteLine("if (retValue != null)");
WriteLine("{");
PushIndent(indent);
if (IsCollection(nodeElement))
{
WriteLine("retValue.ClearAndInitialize(filter, extraProperties);");
if (string.IsNullOrEmpty(subField) )
{
WriteLine("var ret = new SmoCollectionWrapper<{0}>(retValue).Where(c => PassesFinalFilters({1}, c));", nodeType, parentVar);
WriteLine("Logger.Verbose(\"End query {0}\");", nodeType);
WriteLine("return ret;");
}
else
{
WriteLine("List<{0}> subFieldResult = new List<{0}>();", nodeType);
WriteLine("foreach({0} field in retValue)", fieldType);
WriteLine("{");
PushIndent(indent);
WriteLine("{0} subField = field.{1};", nodeType, subField);
WriteLine("if (subField != null)");
WriteLine("{");
PushIndent(indent);
WriteLine("subFieldResult.Add(subField);");
PopIndent();
WriteLine("}");
PopIndent();
WriteLine("}");
WriteLine("var ret = subFieldResult.Where(c => PassesFinalFilters({1}, c));", nodeType, parentVar);
WriteLine("Logger.Verbose(\"End query {0}\");", nodeType);
WriteLine("return ret;");
}
}
else
{
WriteLine("if (refresh)");
WriteLine("{");
PushIndent(indent);
WriteLine("{0}.{1}.Refresh();", parentVar, navigationPath);
PopIndent();
WriteLine("}");
WriteLine("return new SqlSmoObject[] { retValue };");
}
PopIndent();
WriteLine("}");
PopIndent();
WriteLine("}"); // close If
}
WriteLine("return Enumerable.Empty<SqlSmoObject>();");
PopIndent();
WriteLine("}"); // close Query method
PopIndent();
WriteLine("}"); // close Class
PopIndent();
WriteLine("}");
WriteLine("return new SqlSmoObject[] { retValue };");
}
PopIndent();
WriteLine("}");
PopIndent();
WriteLine("}"); // close If
}
WriteLine("return Enumerable.Empty<SqlSmoObject>();");
PopIndent();
WriteLine("}"); // close Query method
PopIndent();
WriteLine("}"); // close Class
PopIndent();
}
#>
}
<#+
public static string[] GetNodes(string xmlFile)
{
List<string> typesList = new List<string>();
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList treeTypes = doc.SelectNodes("/SmoQueryModel/Node");
if (treeTypes != null)
public static string[] GetNodes(string xmlFile)
{
foreach (var type in treeTypes)
{
XmlElement element = type as XmlElement;
if (element != null)
List<string> typesList = new List<string>();
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList treeTypes = doc.SelectNodes("/SmoQueryModel/Node");
if (treeTypes != null)
{
typesList.Add(element.GetAttribute("Name"));
foreach (var type in treeTypes)
{
XmlElement element = type as XmlElement;
if (element != null)
{
typesList.Add(element.GetAttribute("Name"));
}
}
}
}
return typesList.ToArray();
}
return typesList.ToArray();
}
public static XmlElement GetNodeElement(string xmlFile, string nodeName)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
return (XmlElement)doc.SelectSingleNode(string.Format("/SmoQueryModel/Node[@Name='{0}']", nodeName));
}
public static XmlElement GetNavPathElement(string xmlFile, string nodeName, string parent)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlElement navPathElement = (XmlElement)doc.SelectSingleNode(string.Format("/SmoQueryModel/Node[@Name='{0}']/NavigationPath[@Parent='{1}']", nodeName, parent));
return navPathElement;
}
public static string GetNavPathAttribute(XmlElement navPathElement, string attributeName)
{
return navPathElement == null ? null : navPathElement.GetAttribute(attributeName);
}
public static string GetNavigationPath(XmlElement nodeElement, string nodeName, XmlElement navPathElement)
{
string navPathField = GetNavPathAttribute(navPathElement, "Field");
if (!string.IsNullOrEmpty(navPathField))
public static XmlElement GetNodeElement(string xmlFile, string nodeName)
{
return navPathField;
}
// else use pluralized type as this is the most common scenario
string nodeType = GetNodeType(nodeElement, nodeName);
string nodeTypeAccessor = IsCollection(nodeElement) ? string.Format("{0}s", nodeType) : nodeType;
return nodeTypeAccessor;
}
public static string GetNodeType(XmlElement nodeElement, string nodeName)
{
var type = nodeElement.GetAttribute("Type");
if (!string.IsNullOrEmpty(type))
{
return type;
}
// Otherwise assume the type is the node name without "Sql" at the start
var prefix = "Sql";
return nodeName.IndexOf(prefix) == 0 ? nodeName.Substring(prefix.Length) : nodeName;
}
public static bool IsCollection(XmlElement nodeElement)
{
var collection = nodeElement.GetAttribute("Collection");
bool result;
if (bool.TryParse(collection, out result))
{
return result;
}
// Default is true
return true;
}
public static IList<string> GetParents(XmlElement nodeElement, string xmlFile, string parentName)
{
var parentAttr = nodeElement.GetAttribute("Parent");
if (!string.IsNullOrEmpty(parentAttr))
{
return new string[] { parentAttr };
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
return (XmlElement)doc.SelectSingleNode(string.Format("/SmoQueryModel/Node[@Name='{0}']", nodeName));
}
var parentNodes = GetChildren(xmlFile, parentName, "Parent");
if (parentNodes != null && parentNodes.Count > 0)
public static XmlElement GetNavPathElement(string xmlFile, string nodeName, string parent)
{
List<string> parents = new List<string>();
foreach(var node in parentNodes)
{
parents.Add(node.InnerText);
}
return parents;
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlElement navPathElement = (XmlElement)doc.SelectSingleNode(string.Format("/SmoQueryModel/Node[@Name='{0}']/NavigationPath[@Parent='{1}']", nodeName, parent));
return navPathElement;
}
// default to assuming a type is under Database
return new string[] { "Database" };
}
public static List<XmlElement> GetChildren(string xmlFile, string parentName, string childNode)
{
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes(string.Format("/SmoQueryModel/Node[@Name='{0}']/{1}", parentName, childNode));
foreach (var item in nodeList)
public static string GetNavPathAttribute(XmlElement navPathElement, string attributeName)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
public static string GetValidForFlags(string validForStr)
{
List<string> flags = new List<string>();
if (validForStr.Contains("Sql2005"))
{
flags.Add("ValidForFlag.Sql2005");
return navPathElement == null ? null : navPathElement.GetAttribute(attributeName);
}
if (validForStr.Contains("Sql2008"))
public static string GetNavigationPath(XmlElement nodeElement, string nodeName, XmlElement navPathElement)
{
flags.Add("ValidForFlag.Sql2008");
string navPathField = GetNavPathAttribute(navPathElement, "Field");
if (!string.IsNullOrEmpty(navPathField))
{
return navPathField;
}
// else use pluralized type as this is the most common scenario
string nodeType = GetNodeType(nodeElement, nodeName);
string nodeTypeAccessor = IsCollection(nodeElement) ? string.Format("{0}s", nodeType) : nodeType;
return nodeTypeAccessor;
}
if (validForStr.Contains("Sql2012"))
public static string GetNodeType(XmlElement nodeElement, string nodeName)
{
flags.Add("ValidForFlag.Sql2012");
var type = nodeElement.GetAttribute("Type");
if (!string.IsNullOrEmpty(type))
{
return type;
}
// Otherwise assume the type is the node name without "Sql" at the start
var prefix = "Sql";
return nodeName.IndexOf(prefix) == 0 ? nodeName.Substring(prefix.Length) : nodeName;
}
if (validForStr.Contains("Sql2014"))
public static bool IsCollection(XmlElement nodeElement)
{
flags.Add("ValidForFlag.Sql2014");
var collection = nodeElement.GetAttribute("Collection");
bool result;
if (bool.TryParse(collection, out result))
{
return result;
}
// Default is true
return true;
}
if (validForStr.Contains("Sql2016"))
public static IList<string> GetParents(XmlElement nodeElement, string xmlFile, string parentName)
{
flags.Add("ValidForFlag.Sql2016");
var parentAttr = nodeElement.GetAttribute("Parent");
if (!string.IsNullOrEmpty(parentAttr))
{
return new string[] { parentAttr };
}
var parentNodes = GetChildren(xmlFile, parentName, "Parent");
if (parentNodes != null && parentNodes.Count > 0)
{
List<string> parents = new List<string>();
foreach(var node in parentNodes)
{
parents.Add(node.InnerText);
}
return parents;
}
// default to assuming a type is under Database
return new string[] { "Database" };
}
if (validForStr.Contains("Sql2017"))
public static List<XmlElement> GetChildren(string xmlFile, string parentName, string childNode)
{
flags.Add("ValidForFlag.Sql2017");
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes(string.Format("/SmoQueryModel/Node[@Name='{0}']/{1}", parentName, childNode));
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
if (validForStr.Contains("AzureV12"))
public static string GetValidForFlags(string validForStr)
{
flags.Add("ValidForFlag.AzureV12");
}
List<string> flags = new List<string>();
if (validForStr.Contains("Sql2005"))
{
flags.Add("ValidForFlag.Sql2005");
}
if (validForStr.Contains("AllOnPrem"))
{
flags.Add("ValidForFlag.AllOnPrem");
}
if (validForStr.Contains("AllAzure"))
{
flags.Add("ValidForFlag.AllAzure");
}
if (validForStr.Contains("NotSqlDw"))
{
flags.Add("ValidForFlag.NotSqlDw");
}
if (validForStr.Contains("SqlOnDemand"))
{
flags.Add("ValidForFlag.SqlOnDemand");
}
if (validForStr == "NotSqlDemand")
{
flags.Add("ValidForFlag.NotSqlDemand");
}
if (validForStr == "All")
{
flags.Add("ValidForFlag.All");
}
if (validForStr.Contains("Sql2008"))
{
flags.Add("ValidForFlag.Sql2008");
}
return string.Join("|", flags);
}
if (validForStr.Contains("Sql2012"))
{
flags.Add("ValidForFlag.Sql2012");
}
if (validForStr.Contains("Sql2014"))
{
flags.Add("ValidForFlag.Sql2014");
}
if (validForStr.Contains("Sql2016"))
{
flags.Add("ValidForFlag.Sql2016");
}
if (validForStr.Contains("Sql2017"))
{
flags.Add("ValidForFlag.Sql2017");
}
if (validForStr.Contains("AzureV12"))
{
flags.Add("ValidForFlag.AzureV12");
}
if (validForStr.Contains("AllOnPrem"))
{
flags.Add("ValidForFlag.AllOnPrem");
}
if (validForStr.Contains("AllAzure"))
{
flags.Add("ValidForFlag.AllAzure");
}
if (validForStr.Contains("NotSqlDw"))
{
flags.Add("ValidForFlag.NotSqlDw");
}
if (validForStr.Contains("SqlOnDemand"))
{
flags.Add("ValidForFlag.SqlOnDemand");
}
if (validForStr == "NotSqlDemand")
{
flags.Add("ValidForFlag.NotSqlDemand");
}
if (validForStr == "All")
{
flags.Add("ValidForFlag.All");
}
return string.Join("|", flags);
}
#>

View File

@@ -5,13 +5,21 @@
into code using a T4 template.
Key properties:
Name: This maps
Type: Optional SMO type. If not specified, the Name without the Sql prefix is used
Parent: Expected parent type. Needed to codegen the response. if there are multiple parents
then each one
attr.Name: This maps
attr.Type: Optional SMO type. If not specified, the Name without the Sql prefix is used
attr.Parent: Expected parent type. Needed to codegen the response.
Parent: In case a node has multiple parents, chilren of type parents need to be added.
Each parent should have corresponding navigation path.
NavigationPath: For types whose access path differs based on parent or needs custom navigation
this can be used.
attr.Parent: The parent type that this navigation path is valid for
attr.Field: The field to use to navigate to the child type
Filter: Optional filter to apply to the navigation path. This is used to filter out
results that are not of the expected type. For example, the SqlTable type has a
filter on the Schema field to ensure that the table is in the expected schema.
attr.Property: The property to filter on
attr.Field: The field to use from the parent to filter on the property
attr.Type: The type of the field.
-->
<SmoQueryModel>
<!--<Node Name="SqlServer"/> -->
@@ -35,14 +43,37 @@
<Node Name="SqlErrorMessage" Type="UserDefinedMessage" Parent="Server" />
<Node Name="SqlTable" Parent="Database" />
<Node Name="SqlTable">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="Tables" />
<NavigationPath Parent="Schema" Field="Parent.Tables">
<Filter Property="Schema" Field="Name" Type="string" />
</NavigationPath>
</Node>
<Node Name="SqlHistoryTable" Type="Table" Parent="Table" >
<NavigationPath Parent="Table" Type="Table" Field="Parent.Tables" />
</Node>
<Node Name="SqlView" Parent="Database" />
<Node Name="SqlView">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="Views" />
<NavigationPath Parent="Schema" Field="Parent.Views">
<Filter Property="Schema" Field="Name" Type="string" />
</NavigationPath>
</Node>
<Node Name="SqlSynonym" Parent="Database" ValidFor="NotSqlDw" />
<Node Name="SqlSynonym" ValidFor="NotSqlDw">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="Synonyms" />
<NavigationPath Parent="Schema" Field="Parent.Synonyms">
<Filter Property="Schema" Field="Name" Type="string" />
</NavigationPath>
</Node>
<Node Name="SqlColumn" Parent="TableViewTableTypeBase"/>
<Node Name="SqlIndex" Parent="TableViewTableTypeBase">
@@ -75,17 +106,68 @@
<Node Name="SqlRule" Parent="Database" />
<Node Name="SqlDefault" Parent="Database" />
-->
<Node Name="SqlSequence" Parent="Database" />
<Node Name="SqlSequence">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="Sequences" />
<NavigationPath Parent="Schema" Field="Parent.Sequences">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlUserDefinedDataType" Parent="Database" ValidFor="NotSqlDw" />
<Node Name="SqlUserDefinedDataType" ValidFor="NotSqlDw">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="UserDefinedDataTypes" />
<NavigationPath Parent="Schema" Field="Parent.UserDefinedDataTypes">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlUserDefinedTableType" Parent="Database" />
<Node Name="SqlXmlSchemaCollection" />
<Node Name="SqlUserDefinedType" />
<Node Name="SqlUserDefinedTableType">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="UserDefinedTableTypes" />
<NavigationPath Parent="Schema" Field="Parent.UserDefinedTableTypes">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlUserDefinedFunction" />
<Node Name="SqlXmlSchemaCollection">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="XmlSchemaCollections" />
<NavigationPath Parent="Schema" Field="Parent.XmlSchemaCollections">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlUserDefinedAggregate" />
<Node Name="SqlUserDefinedType">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="UserDefinedTypes" />
<NavigationPath Parent="Schema" Field="Parent.UserDefinedTypes">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlUserDefinedFunction">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<Navigation Path="Database" Field="UserDefinedFunctions" />
<NavigationPath Parent="Schema" Field="Parent.UserDefinedFunctions">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlUserDefinedAggregate">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="UserDefinedAggregates" />
<NavigationPath Parent="Schema" Field="Parent.UserDefinedAggregates">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlFileGroup" />
<Node Name="SqlFile" Type="DataFile" Parent="FileGroup" >
@@ -135,7 +217,14 @@
<Node Name="SqlExternalDataSource" />
<Node Name="SqlExternalFileFormat" />
<Node Name="SqlProcedure" Type="StoredProcedure"/>
<Node Name="SqlProcedure" Type="StoredProcedure">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="StoredProcedures" />
<NavigationPath Parent="Schema" Field="Parent.StoredProcedures">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlExtendedStoredProcedure" />
<Node Name="SqlSubroutineParameter" Type="Parameter" >
<Parent>StoredProcedure</Parent>

View File

@@ -62,10 +62,11 @@
<Node Name="ServerLevelServerTriggers" LocLabel="SR.SchemaHierarchy_ServerTriggers" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="ServerLevelServerTrigger" ChildQuerierTypes="SqlServerDdlTrigger"/>
<Node Name="ServerLevelErrorMessages" LocLabel="SR.SchemaHierarchy_ErrorMessages" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="ServerLevelErrorMessage" ChildQuerierTypes="SqlErrorMessage"/>
<Node Name="Database" LocLabel="string.Empty" Image="Database" BaseClass="ModelBased" NodeType="Database" IsAsyncLoad="" Strategy="CreateModel">
<Child Name="Tables"/>
<Child Name="Views"/>
<Child Name="Synonyms"/>
<Node Name="Database" LocLabel="string.Empty" Image="Database" BaseClass="ModelBased" NodeType="Database" IsAsyncLoad="" Strategy="CreateModel" TreeNode="ExpandableSchemaTreeNode" PutFoldersAfterNodes="true">
<ConditionalChildQuerierType Name="SqlSchema" SettingsFlag="GroupBySchema"/>
<Child Name="Tables" SettingsFlag="!GroupBySchema"/>
<Child Name="Views" SettingsFlag="!GroupBySchema"/>
<Child Name="Synonyms" SettingsFlag="!GroupBySchema"/>
<Child Name="Programmability"/>
<Child Name="ExternalResources"/>
<Child Name="ServiceBroker"/>
@@ -73,6 +74,13 @@
<Child Name="Security"/>
</Node>
<Node Name="ExpandableSchema" LocLabel="string.empty" BaseClass="ModelBased" Strategy="CreateModel">
<Child Name="Tables"/>
<Child Name="Views"/>
<Child Name="Synonyms"/>
<Child Name="ExpandableSchemaProgrammability"/>
</Node>
<Node Name="Tables" LocLabel="SR.SchemaHierarchy_Tables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableTreeNode">
<Filters>
<Filter Property="IsSystemObject" Value="0" Type="bool" />
@@ -115,15 +123,21 @@
<Node Name="Synonyms" LocLabel="SR.SchemaHierarchy_Synonyms" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="Synonym" ChildQuerierTypes="SqlSynonym" ValidFor="AllOnPrem|AzureV12"/>
<Node Name="Programmability" LocLabel="SR.SchemaHierarchy_Programmability" BaseClass="ModelBased" ValidFor="NotSqlDemand">
<Child Name="StoredProcedures"/>
<Child Name="Functions"/>
<Child Name="StoredProcedures" SettingsFlag="!GroupBySchema"/>
<Child Name="Functions" SettingsFlag="!GroupBySchema"/>
<Child Name="DatabaseTriggers"/>
<Child Name="Assemblies"/>
<Child Name="Types"/>
<Child Name="Types" SettingsFlag="!GroupBySchema"/>
<!--
<Child Name="Rules"/>
<Child Name="Defaults"/>
-->
<Child Name="Sequences" SettingsFlag="!GroupBySchema"/>
</Node>
<Node Name="ExpandableSchemaProgrammability" LocLabel="SR.SchemaHierarchy_Programmability" BaseClass="ModelBased" ValidFor="NotSqlDemand">
<Child Name="StoredProcedures"/>
<Child Name="Functions"/>
<Child Name="Types"/>
<Child Name="Sequences"/>
</Node>
<Node Name="ExternalResources" LocLabel="SR.SchemaHierarchy_ExternalResources" BaseClass="ModelBased" TreeNode="ExternalResourceTreeNode" ValidFor="Sql2016OrHigher|AzureV12|SqlOnDemand">
@@ -511,6 +525,7 @@
<UniqueTreeNode Name="ExternalTableTreeNode"/>
<UniqueTreeNode Name="ExternalResourceTreeNode"/>
<UniqueTreeNode Name="HistoryTableTreeNode" />
<UniqueTreeNode Name="ExpandableSchemaTreeNode" Type="Schema"/>
</CodeGenOptions>
<!-- WARNING: Specifying reverse dependencies that could load large numbers of objects will be detrimental to performance. -->

View File

@@ -14,11 +14,13 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
{
public static int DefaultCreateSessionTimeout = 45;
public static int DefaultExpandTimeout = 45;
public static bool DefaultGroupBySchema = false;
public ObjectExplorerSettings()
{
CreateSessionTimeout = DefaultCreateSessionTimeout;
ExpandTimeout = DefaultExpandTimeout;
GroupBySchema = DefaultGroupBySchema;
}
/// <summary>
@@ -30,5 +32,11 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
/// Number of seconds to wait before fail expand request with timeout error
/// </summary>
public int ExpandTimeout { get; set; }
/// <summary>
/// Moves Schema to the top level of OE and then move schema-bound nodes under it.
/// </summary>
/// <value></value>
public bool GroupBySchema { get; set; }
}
}

View File

@@ -331,6 +331,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
{
Logger.Write(TraceEventType.Verbose, "HandleDidChangeConfigurationNotification");
this.CurrentSettings = configChangeParams.Settings;
// Propagate the changes to the event handlers
var configUpdateTasks = ConfigChangeCallbacks.Select(
t => t(configChangeParams.Settings, CurrentSettings, eventContext));

View File

@@ -19,8 +19,10 @@ using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.SqlContext;
using Microsoft.SqlTools.ServiceLayer.Test.Common;
using Microsoft.SqlTools.ServiceLayer.Test.Common.Extensions;
using Microsoft.SqlTools.ServiceLayer.Workspace;
using NUnit.Framework;
using static Microsoft.SqlTools.ServiceLayer.ObjectExplorer.ObjectExplorerService;
@@ -210,6 +212,50 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
});
}
[Test]
public async Task GroupBySchemaisDisabled()
{
string query = @"Create schema t1
GO
Create schema t2
GO";
string databaseName = "#testDb#";
await RunTest(databaseName, query, "TestDb", async (testDbName, session) =>
{
WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.SqlTools.ObjectExplorer = new ObjectExplorerSettings() { GroupBySchema = false };
var databaseNode = session.Root.ToNodeInfo();
var databaseChildren = await _service.ExpandNode(session, databaseNode.NodePath);
Assert.True(databaseChildren.Nodes.Any(t => t.Label == SR.SchemaHierarchy_Tables), "Tables node should be found in database node when group by schema is disabled");
Assert.True(databaseChildren.Nodes.Any(t => t.Label == SR.SchemaHierarchy_Views), "Views node should be found in database node when group by schema is disabled");
});
}
[Test]
public async Task GroupBySchemaisEnabled()
{
string query = @"Create schema t1
GO
Create schema t2
GO";
string databaseName = "#testDb#";
await RunTest(databaseName, query, "TestDb", async (testDbName, session) =>
{
WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.SqlTools.ObjectExplorer = new ObjectExplorerSettings() { GroupBySchema = true };
var databaseNode = session.Root.ToNodeInfo();
var databaseChildren = await _service.ExpandNode(session, databaseNode.NodePath);
Assert.True(databaseChildren.Nodes.Any(t => t.Label == "t1"), "Schema node t1 should be found in database node when group by schema is enabled");
Assert.True(databaseChildren.Nodes.Any(t => t.Label == "t2"), "Schema node t2 should be found in database node when group by schema is enabled");
Assert.False(databaseChildren.Nodes.Any(t => t.Label == SR.SchemaHierarchy_Tables), "Tables node should not be found in database node when group by schema is enabled");
Assert.False(databaseChildren.Nodes.Any(t => t.Label == SR.SchemaHierarchy_Views), "Views node should not be found in database node when group by schema is enabled");
Assert.True(databaseChildren.Nodes.Any(t => t.Label == SR.SchemaHierarchy_Programmability), "Programmability node should be found in database node when group by schema is enabled");
var lastSchemaPosition = Array.FindLastIndex(databaseChildren.Nodes, t => t.ObjectType == nameof(NodeTypes.ExpandableSchema));
var firstNonSchemaPosition = Array.FindIndex(databaseChildren.Nodes, t => t.ObjectType != nameof(NodeTypes.ExpandableSchema));
Assert.True(lastSchemaPosition < firstNonSchemaPosition, "Schema nodes should be before non-schema nodes");
WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.SqlTools.ObjectExplorer = new ObjectExplorerSettings() { GroupBySchema = false };
});
}
private async Task VerifyRefresh(ObjectExplorerSession session, string tablePath, string tableName, bool deleted = true)
{
//Refresh Root
@@ -217,7 +263,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
//Verify tables cache is empty
var rootChildrenCache = session.Root.GetChildren();
var tablesCache = rootChildrenCache.First(x => x.Label == SR.SchemaHierarchy_Tables).GetChildren();
var tablesCache = rootChildrenCache.First(x => x.Label == SR.SchemaHierarchy_Tables).GetChildren();
Assert.False(tablesCache.Any());
//Expand Tables
@@ -292,7 +338,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
ConnectionDetails details = connectParams.Connection;
string uri = ObjectExplorerService.GenerateUri(details);
var session = await _service.DoCreateSession(details, uri);
var session = await _service.DoCreateSession(details, uri);
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "OE session created for database: {0}", databaseName));
return session;
}
@@ -403,7 +449,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
/// </summary>
private async Task<NodeInfo> FindNodeByLabel(NodeInfo node, ObjectExplorerSession session, string label)
{
if(node != null && node.Label == label)
if (node != null && node.Label == label)
{
return node;
}
@@ -434,7 +480,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
{
// These are node types for which the label doesn't include a schema
// (usually because the objects themselves aren't schema-bound)
var schemalessLabelNodeTypes = new List<string> () {
var schemalessLabelNodeTypes = new List<string>() {
"Column",
"Key",
"Constraint",

View File

@@ -0,0 +1,66 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.Linq;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
using Microsoft.SqlTools.ServiceLayer.SqlContext;
using Microsoft.SqlTools.ServiceLayer.Workspace;
using Moq;
using NUnit.Framework;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
{
class GroupBySchemaTests
{
Mock<DatabaseChildFactory> factory;
Mock<TreeNode> node;
[SetUp]
public void init()
{
factory = new Mock<DatabaseChildFactory>();
factory.SetupGet(c => c.ChildQuerierTypes).Returns(null as Type[]);
factory.Setup(c => c.CreateChild(It.IsAny<TreeNode>(), It.IsAny<SqlSmoObject>())).Returns((TreeNode node, Schema obj) => {
return new TreeNode(){
Label = obj.Name,
NodeType = nameof(NodeTypes.Schemas)
};
});
factory.CallBase = true;
Mock<SmoQueryContext> context = new Mock<SmoQueryContext>(new Server(), null);
context.CallBase = true;
context.Object.ValidFor = ValidForFlag.None;
node = new Mock<TreeNode>();
node.Setup(n => n.GetContext()).Returns(context.Object);
}
[Test]
public void SchemaBasedFoldersExcludedWhenGroupBySchemaIsEnabled()
{
WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.SqlTools.ObjectExplorer = new ObjectExplorerSettings() { GroupBySchema = true };
var children = factory.Object.Expand(node.Object, true, "TestDB", true, new System.Threading.CancellationToken());
Assert.False(children.Any(c => c.Label == "Tables"), "Tables subfolder in database should be excluded when group by schema is enabled");
Assert.False(children.Any(c => c.Label == "Views"), "Views subfolder in database should be excluded when group by schema is enabled");
Assert.False(children.Any(c => c.Label == "Synonyms"), "Synonyms subfolder in database should be excluded when group by schema is enabled");
}
[Test]
public void SchemaBasedFoldersIncludedWhenGroupBySchemaIsDisabled()
{
WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.SqlTools.ObjectExplorer = new ObjectExplorerSettings() { GroupBySchema = false };
var children = factory.Object.Expand(node.Object, true, "TestDB", true, new System.Threading.CancellationToken());
Assert.True(children.Any(c => c.Label == "Tables"), "Tables subfolder in database should be included when group by schema is disabled");
Assert.True(children.Any(c => c.Label == "Views"), "Views subfolder in database should be included when group by schema is disabled");
Assert.True(children.Any(c => c.Label == "Synonyms"), "Synonyms subfolder in database should be included when group by schema is disabled");
}
}
}

View File

@@ -193,5 +193,30 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
string expectedTableQuerierFilters = "[(@IsSystemObject = 1) and ((@IsSystemObject = 1))]";
Assert.That(invalidQuerierType, Is.EqualTo(expectedTableQuerierFilters), "GetPropertyFilter did not construct the URN filter string as expected when excluding filters that don't match the querier type.");
}
[Test]
public void TestAddPropertyFiltersToExistingURNs()
{
var Node = new List<NodePropertyFilter> {
TemporalFilter,
LedgerHistoryFilter
};
var nodeList = new List<INodeFilter> {
new NodePropertyFilter(){
Property = "Schema",
Values = new List<object> {"jsdafl983!@$#%535343]]]][[["},
Type = typeof(string),
ValidFor = ValidForFlag.Sql2022OrHigher
}
};
string allFiltersValid = INodeFilter.GetPropertyFilter(Node, typeof(SqlHistoryTableQuerier), ValidForFlag.Sql2022OrHigher);
string expectedAllFilters = "[(@TemporalType = 1) and (@LedgerType = 1)]";
Assert.That(allFiltersValid, Is.EqualTo(expectedAllFilters), "GetPropertyFilter did not construct the URN filter string as expected");
string newUrn = INodeFilter.AddPropertyFilterToFilterString(allFiltersValid, nodeList, typeof(SqlHistoryTableQuerier), ValidForFlag.Sql2022OrHigher);
string expectedNewUrn = "[(@TemporalType = 1) and (@LedgerType = 1) and (@Schema = 'jsdafl983!@$#%535343]]]][[[')]";
Assert.That(newUrn, Is.EqualTo(expectedNewUrn), "GetPropertyFilter did not construct the URN filter string as expected");
}
}
}