mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-15 17:23:32 -05:00
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
internal partial class DatabaseInstanceTreeNode
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the context and ensures that
|
||||
/// </summary>
|
||||
protected override void EnsureContextInitialized()
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
base.EnsureContextInitialized();
|
||||
Database db = SmoObject as Database;
|
||||
if (context != null && db != null)
|
||||
{
|
||||
context.Database = db;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a folder node in the tree
|
||||
/// </summary>
|
||||
public class FolderNode : SmoTreeNode
|
||||
{
|
||||
/// <summary>
|
||||
/// For folders, this copies the context of its parent if available
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override object GetContext()
|
||||
{
|
||||
return Parent?.GetContext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For folders, searches for its parent's SMO object rather than copying for itself
|
||||
/// </summary>
|
||||
/// <returns><see cref="NamedSmoObject"/> from this parent's parent, or null if not found</returns>
|
||||
public override NamedSmoObject GetParentSmoObject()
|
||||
{
|
||||
return ParentAs<SmoTreeNode>()?.GetParentSmoObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
//
|
||||
// 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.Data.Common;
|
||||
using System.Data.SqlClient;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.Extensibility;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Server node implementation
|
||||
/// </summary>
|
||||
public class ServerNode : TreeNode
|
||||
{
|
||||
private ConnectionSummary connectionSummary;
|
||||
private ServerInfo serverInfo;
|
||||
private string connectionUri;
|
||||
private Lazy<SmoQueryContext> context;
|
||||
private ConnectionService connectionService;
|
||||
private SmoServerCreator serverCreator;
|
||||
|
||||
public ServerNode(ConnectionCompleteParams connInfo, IMultiServiceProvider serviceProvider)
|
||||
: base()
|
||||
{
|
||||
Validate.IsNotNull(nameof(connInfo), connInfo);
|
||||
Validate.IsNotNull("connInfo.ConnectionSummary", connInfo.ConnectionSummary);
|
||||
Validate.IsNotNull(nameof(serviceProvider), serviceProvider);
|
||||
|
||||
this.connectionSummary = connInfo.ConnectionSummary;
|
||||
this.serverInfo = connInfo.ServerInfo;
|
||||
this.connectionUri = connInfo.OwnerUri;
|
||||
|
||||
this.connectionService = serviceProvider.GetService<ConnectionService>();
|
||||
|
||||
this.context = new Lazy<SmoQueryContext>(() => CreateContext(serviceProvider));
|
||||
|
||||
NodeValue = connectionSummary.ServerName;
|
||||
IsAlwaysLeaf = false;
|
||||
NodeType = NodeTypes.ServerInstance.ToString();
|
||||
NodeTypeId = NodeTypes.ServerInstance;
|
||||
Label = GetConnectionLabel();
|
||||
}
|
||||
|
||||
internal SmoServerCreator ServerCreator
|
||||
{
|
||||
get
|
||||
{
|
||||
if (serverCreator == null)
|
||||
{
|
||||
ServerCreator = new SmoServerCreator();
|
||||
}
|
||||
return serverCreator;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.serverCreator = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the label to display to the user.
|
||||
/// </summary>
|
||||
internal string GetConnectionLabel()
|
||||
{
|
||||
string userName = connectionSummary.UserName;
|
||||
|
||||
// TODO Domain and username is not yet supported on .Net Core.
|
||||
// Consider passing as an input from the extension where this can be queried
|
||||
//if (string.IsNullOrWhiteSpace(userName))
|
||||
//{
|
||||
// userName = Environment.UserDomainName + @"\" + Environment.UserName;
|
||||
//}
|
||||
|
||||
// TODO Consider adding IsAuthenticatingDatabaseMaster check in the code and
|
||||
// referencing result here
|
||||
if (!string.IsNullOrWhiteSpace(connectionSummary.DatabaseName) &&
|
||||
string.Compare(connectionSummary.DatabaseName, CommonConstants.MasterDatabaseName, StringComparison.OrdinalIgnoreCase) != 0 &&
|
||||
(serverInfo.IsCloud /* || !ci.IsAuthenticatingDatabaseMaster */))
|
||||
{
|
||||
// We either have an azure with a database specified or a Denali database using a contained user
|
||||
userName += ", " + connectionSummary.DatabaseName;
|
||||
}
|
||||
|
||||
string label;
|
||||
if (string.IsNullOrWhiteSpace(userName))
|
||||
{
|
||||
label = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"{0} ({1} {2})",
|
||||
connectionSummary.ServerName,
|
||||
"SQL Server",
|
||||
serverInfo.ServerVersion);
|
||||
}
|
||||
else
|
||||
{
|
||||
label = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"{0} ({1} {2} - {3})",
|
||||
connectionSummary.ServerName,
|
||||
"SQL Server",
|
||||
serverInfo.ServerVersion,
|
||||
userName);
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
private SmoQueryContext CreateContext(IMultiServiceProvider serviceProvider)
|
||||
{
|
||||
string exceptionMessage;
|
||||
ConnectionInfo connectionInfo;
|
||||
SqlConnection connection = null;
|
||||
// Get server object from connection
|
||||
if (!connectionService.TryFindConnection(this.connectionUri, out connectionInfo) ||
|
||||
connectionInfo.AllConnections == null || connectionInfo.AllConnections.Count == 0)
|
||||
{
|
||||
ErrorStateMessage = string.Format(CultureInfo.CurrentCulture,
|
||||
SR.ServerNodeConnectionError, connectionSummary.ServerName);
|
||||
return null;
|
||||
}
|
||||
//TODO: figure out how to use existing connections
|
||||
DbConnection dbConnection = connectionInfo.AllConnections.First();
|
||||
ReliableSqlConnection reliableSqlConnection = dbConnection as ReliableSqlConnection;
|
||||
SqlConnection sqlConnection = dbConnection as SqlConnection;
|
||||
if (reliableSqlConnection != null)
|
||||
{
|
||||
connection = reliableSqlConnection.GetUnderlyingConnection();
|
||||
}
|
||||
else if (sqlConnection != null)
|
||||
{
|
||||
connection = sqlConnection;
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorStateMessage = string.Format(CultureInfo.CurrentCulture,
|
||||
SR.ServerNodeConnectionError, connectionSummary.ServerName);
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Server server = ServerCreator.Create(connection);
|
||||
return new SmoQueryContext(server, serviceProvider)
|
||||
{
|
||||
Parent = server
|
||||
};
|
||||
}
|
||||
catch (ConnectionFailureException cfe)
|
||||
{
|
||||
exceptionMessage = cfe.Message;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exceptionMessage = ex.Message;
|
||||
}
|
||||
|
||||
Logger.Write(LogLevel.Error, "Exception at ServerNode.CreateContext() : " + exceptionMessage);
|
||||
this.ErrorStateMessage = string.Format(SR.TreeNodeError, exceptionMessage);
|
||||
return null;
|
||||
}
|
||||
|
||||
public override object GetContext()
|
||||
{
|
||||
return context.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal for testing purposes only
|
||||
/// </summary>
|
||||
internal class SmoServerCreator
|
||||
{
|
||||
public virtual Server Create(SqlConnection connection)
|
||||
{
|
||||
ServerConnection serverConn = new ServerConnection(connection);
|
||||
return new Server(serverConn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
public class SmoChildFactoryBase : ChildFactory
|
||||
{
|
||||
public override IEnumerable<string> ApplicableParents()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override IEnumerable<TreeNode> Expand(TreeNode parent)
|
||||
{
|
||||
//parent.BeginChildrenInit();
|
||||
try
|
||||
{
|
||||
List<TreeNode> allChildren = new List<TreeNode>();
|
||||
OnExpandPopulateFolders(allChildren, parent);
|
||||
RemoveFoldersFromInvalidSqlServerVersions(allChildren, parent);
|
||||
OnExpandPopulateNonFolders(allChildren, parent);
|
||||
OnBeginAsyncOperations(parent);
|
||||
return allChildren;
|
||||
}
|
||||
finally
|
||||
{
|
||||
//parent.EndChildrenInit();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates any folders for a given parent node
|
||||
/// </summary>
|
||||
/// <param name="allChildren">List to which nodes should be added</param>
|
||||
/// <param name="parent">Parent the nodes are being added to</param>
|
||||
protected virtual void OnExpandPopulateFolders(IList<TreeNode> allChildren, TreeNode parent)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates any non-folder nodes such as specific items in the tree.
|
||||
/// </summary>
|
||||
/// <param name="allChildren">List to which nodes should be added</param>
|
||||
/// <param name="parent">Parent the nodes are being added to</param>
|
||||
protected virtual void OnExpandPopulateNonFolders(IList<TreeNode> allChildren, TreeNode parent)
|
||||
{
|
||||
if (ChildQuerierTypes == null)
|
||||
{
|
||||
// This node does not support non-folder children
|
||||
return;
|
||||
}
|
||||
SmoQueryContext context = parent.GetContextAs<SmoQueryContext>();
|
||||
Validate.IsNotNull(nameof(context), context);
|
||||
IEnumerable<SmoQuerier> queriers = context.ServiceProvider.GetServices<SmoQuerier>(q => IsCompatibleQuerier(q));
|
||||
foreach (var querier in queriers)
|
||||
{
|
||||
foreach(var smoObject in querier.Query(context))
|
||||
{
|
||||
if (smoObject == null)
|
||||
{
|
||||
Console.WriteLine("smoObject should not be null");
|
||||
}
|
||||
TreeNode childNode = CreateChild(parent, smoObject);
|
||||
if (childNode != null)
|
||||
{
|
||||
allChildren.Add(childNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsCompatibleQuerier(SmoQuerier querier)
|
||||
{
|
||||
if (ChildQuerierTypes == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Type actualType = querier.GetType();
|
||||
foreach (Type childType in ChildQuerierTypes)
|
||||
{
|
||||
// We will accept any querier that is compatible with the listed querier type
|
||||
if (childType.IsAssignableFrom(actualType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filters out invalid folders if they cannot be displayed for the current server version
|
||||
/// </summary>
|
||||
/// <param name="allChildren">List to which nodes should be added</param>
|
||||
/// <param name="parent">Parent the nodes are being added to</param>
|
||||
protected virtual void RemoveFoldersFromInvalidSqlServerVersions(IList<TreeNode> allChildren, TreeNode parent)
|
||||
{
|
||||
}
|
||||
|
||||
// TODO Assess whether async operations node is required
|
||||
protected virtual void OnBeginAsyncOperations(TreeNode parent)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanCreateChild(TreeNode parent, object context)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override TreeNode CreateChild(TreeNode parent, object context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected virtual void InitializeChild(TreeNode child, object context)
|
||||
{
|
||||
NamedSmoObject smoObj = context as NamedSmoObject;
|
||||
if (smoObj == null)
|
||||
{
|
||||
Debug.WriteLine("context is not a NamedSmoObject. type: " + context.GetType());
|
||||
}
|
||||
else
|
||||
{
|
||||
SmoTreeNode childAsMeItem = (SmoTreeNode)child;
|
||||
childAsMeItem.CacheInfoFromModel(smoObj);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual Type[] ChildQuerierTypes {
|
||||
get
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if any final validation of the object to be added passes, and false
|
||||
/// if validation fails. This provides a chance to filter specific items out of a list
|
||||
/// </summary>
|
||||
/// <param name="parent"></param>
|
||||
/// <param name="contextObject"></param>
|
||||
/// <returns>boolean</returns>
|
||||
public virtual bool PassesFinalFilters(TreeNode parent, object context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// 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.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapper to convert non-generic Smo enumerables to generic enumerable types for easier use in
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class SmoCollectionWrapper<T> : IEnumerable<T>
|
||||
where T : SqlSmoObject
|
||||
{
|
||||
private SmoCollectionBase collection;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor which accepts a <see cref="SmoCollectionBase"/> containing the objects
|
||||
/// to wrap
|
||||
/// </summary>
|
||||
/// <param name="collection"><see cref="SmoCollectionBase"/> or null if none were set</param>
|
||||
public SmoCollectionWrapper(SmoCollectionBase collection)
|
||||
{
|
||||
this.collection = collection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IEnumerable{T}.GetEnumerator"/>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
if (collection == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
foreach(Object obj in collection)
|
||||
{
|
||||
yield return (T)obj;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IEnumerable.GetEnumerator"/>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return collection?.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.Extensibility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="SmoQuerier"/> handles SMO queries for one or more SMO object types.
|
||||
/// The <see cref="SupportedObjectTypes"/> property defines which types can be queried.
|
||||
///
|
||||
/// To query multiple
|
||||
/// </summary>
|
||||
public abstract class SmoQuerier : IComposableService
|
||||
{
|
||||
public abstract Type[] SupportedObjectTypes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Queries SMO for a collection of objects using the <see cref="SmoQueryContext"/>
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public abstract IEnumerable<SqlSmoObject> Query(SmoQueryContext context);
|
||||
|
||||
internal IMultiServiceProvider ServiceProvider
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public void SetServiceProvider(IMultiServiceProvider provider)
|
||||
{
|
||||
ServiceProvider = provider;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// 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.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.Extensibility;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Context object containing key properties needed to query for SMO objects
|
||||
/// </summary>
|
||||
public class SmoQueryContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a context object with a server to use as the basis for any queries
|
||||
/// </summary>
|
||||
/// <param name="server"></param>
|
||||
public SmoQueryContext(Server server, IMultiServiceProvider serviceProvider)
|
||||
{
|
||||
Server = server;
|
||||
ServiceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The server SMO will query against
|
||||
/// </summary>
|
||||
public Server Server { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional Database context object to query against
|
||||
/// </summary>
|
||||
public Database Database { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parent of a give node to use for queries
|
||||
/// </summary>
|
||||
public SmoObjectBase Parent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A query loader that can be used to find <see cref="SmoQuerier"/> objects
|
||||
/// for specific SMO types
|
||||
/// </summary>
|
||||
public IMultiServiceProvider ServiceProvider { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to cast a parent to a specific type
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public T ParentAs<T>()
|
||||
where T : TreeNode
|
||||
{
|
||||
return Parent as T;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ObjectExplorerService"/> if available, by looking it up
|
||||
/// from the <see cref="ServiceProvider"/>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="InvalidOperationException">
|
||||
/// Thrown if the <see cref="ServiceProvider"/> is not set or the <see cref="ObjectExplorerService"/>
|
||||
/// isn't available from that provider
|
||||
/// </exception>
|
||||
public ObjectExplorerService GetObjectExplorerService()
|
||||
{
|
||||
if (ServiceProvider == null)
|
||||
{
|
||||
throw new InvalidOperationException(SqlTools.Hosting.Localization.sr.ServiceProviderNotSet);
|
||||
}
|
||||
ObjectExplorerService service = ServiceProvider.GetService<ObjectExplorerService>();
|
||||
if (service == null)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
|
||||
SqlTools.Hosting.Localization.sr.ServiceNotFound, nameof(ObjectExplorerService)));
|
||||
}
|
||||
|
||||
return service;
|
||||
}
|
||||
/// <summary>
|
||||
/// Copies the context for use by another node
|
||||
/// </summary>
|
||||
/// <param name="parent">New Parent to set</param>
|
||||
/// <returns>new <see cref="SmoQueryContext"/> with all fields except <see cref="Parent"/> the same</returns>
|
||||
public SmoQueryContext CopyWithParent(SmoObjectBase parent)
|
||||
{
|
||||
SmoQueryContext context = new SmoQueryContext(this.Server, this.ServiceProvider)
|
||||
{
|
||||
Database = this.Database,
|
||||
Parent = parent
|
||||
};
|
||||
return context;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,215 @@
|
||||
<#@ template debug="false" hostspecific="true" language="C#" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Xml.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" #>
|
||||
// This file was generated by a T4 Template. Do not modify directly, instead update the SmoQueryModelDefinition.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".
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Composition;
|
||||
using System.Linq;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlServer.Management.Smo.Broker;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
<#
|
||||
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);
|
||||
|
||||
string queryBaseClass = "SmoQuerier";
|
||||
PushIndent(indent);
|
||||
WriteLine("");
|
||||
WriteLine(string.Format("[Export(typeof({0}))]", queryBaseClass));
|
||||
WriteLine(string.Format("internal partial class {0}Querier: {1}", nodeName, queryBaseClass));
|
||||
WriteLine("{");
|
||||
PushIndent(indent);
|
||||
|
||||
// Supported Types
|
||||
WriteLine("Type[] supportedTypes = new Type[] { typeof("+ nodeType + ") };");
|
||||
WriteLine("");
|
||||
WriteLine("public override Type[] SupportedObjectTypes { get { return supportedTypes; } }");
|
||||
WriteLine("");
|
||||
|
||||
// Query impl
|
||||
WriteLine("public override IEnumerable<SqlSmoObject> Query(SmoQueryContext context)");
|
||||
WriteLine("{");
|
||||
PushIndent(indent);
|
||||
|
||||
// TODO Allow override of the navigation path
|
||||
foreach(var parentType in parents)
|
||||
{
|
||||
string parentVar = string.Format("parent{0}", parentType);
|
||||
WriteLine(string.Format("{0} {1} = context.Parent as {0};", parentType, parentVar));
|
||||
WriteLine(string.Format("if ({0} != null)", parentVar));
|
||||
WriteLine("{");
|
||||
PushIndent(indent);
|
||||
|
||||
string navigationPath = GetNavigationPath(nodeElement, xmlFile, nodeName, parentType);
|
||||
WriteLine(string.Format("var retValue = {0}.{1};", parentVar, navigationPath));
|
||||
WriteLine("if(retValue != null)");
|
||||
WriteLine("{");
|
||||
PushIndent(indent);
|
||||
if (IsCollection(nodeElement))
|
||||
{
|
||||
WriteLine(string.Format("return new SmoCollectionWrapper<{0}>(retValue);", nodeType));
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
foreach (var type in treeTypes)
|
||||
{
|
||||
XmlElement element = type as XmlElement;
|
||||
if (element != null)
|
||||
{
|
||||
typesList.Add(element.GetAttribute("Name"));
|
||||
}
|
||||
}
|
||||
}
|
||||
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 string GetNavPathField(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?.GetAttribute("Field");
|
||||
}
|
||||
|
||||
public static string GetNavigationPath(XmlElement nodeElement, string xmlFile, string nodeName, string parentName)
|
||||
{
|
||||
string navPathField = GetNavPathField(xmlFile, nodeName, parentName);
|
||||
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;
|
||||
}
|
||||
|
||||
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 };
|
||||
}
|
||||
|
||||
var parentNodes = GetChildren(xmlFile, parentName, "Parent");
|
||||
if (parentNodes != null && parentNodes.Count > 0)
|
||||
{
|
||||
List<string> parents = new List<string>();
|
||||
int i = 0;
|
||||
foreach(var node in parentNodes)
|
||||
{
|
||||
parents.Add(node.InnerText);
|
||||
}
|
||||
return parents;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
XmlElement itemAsElement = item as XmlElement;
|
||||
if (itemAsElement != null)
|
||||
{
|
||||
retElements.Add(itemAsElement);
|
||||
}
|
||||
}
|
||||
return retElements;
|
||||
}
|
||||
|
||||
#>
|
||||
@@ -0,0 +1,146 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--
|
||||
This XML file defines how to query for a given SMO type based on a parent/child or
|
||||
XPath relationship. From this file, the paths to query each type should be buildable
|
||||
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
|
||||
NavigationPath: For types whose access path differs based on parent or needs custom navigation
|
||||
this can be used.
|
||||
|
||||
-->
|
||||
<SmoQueryModel>
|
||||
<!--<Node Name="SqlServer"/> -->
|
||||
<Node Name="SqlDatabase" Type="Database" Parent="Server" />
|
||||
<Node Name="SqlLinkedServerLogin" Type="LinkedServer" Parent="Server"/>
|
||||
<Node Name="SqlLogin" Type="Login" Parent="Server" />
|
||||
<Node Name="SqlServerRole" Type="" Parent="Server" >
|
||||
<NavigationPath Parent="Server" Field="Roles" />
|
||||
</Node>
|
||||
|
||||
<Node Name="SqlCredential" Parent="Server" />
|
||||
<Node Name="SqlCryptographicProvider" Parent="Server" />
|
||||
<Node Name="SqlServerAudit" Type="Audit" Parent="Server" />
|
||||
<Node Name="SqlServerAuditSpecification" Type="ServerAuditSpecification" Parent="Server"/>
|
||||
|
||||
<Node Name="SqlEndpoint" Parent="Server"/>
|
||||
<Node Name="SqlLinkedServer" Parent="Server" />
|
||||
<Node Name="SqlServerDdlTrigger" Parent="Server" >
|
||||
<NavigationPath Parent="Server" Field="Triggers" />
|
||||
</Node>
|
||||
|
||||
<Node Name="SqlErrorMessage" Type="UserDefinedMessage" Parent="Server" />
|
||||
|
||||
<Node Name="SqlTable" Parent="Database" />
|
||||
<Node Name="SqlView" Parent="Database" />
|
||||
|
||||
<Node Name="SqlSynonym" Parent="Database" />
|
||||
|
||||
<Node Name="SqlColumn" Parent="TableViewTableTypeBase"/>
|
||||
<Node Name="SqlIndex" Parent="TableViewTableTypeBase">
|
||||
<NavigationPath Parent="TableViewTableTypeBase" Field="Indexes" />
|
||||
</Node>
|
||||
|
||||
<Node Name="SqlCheck" Parent="Table"/>
|
||||
<Node Name="SqlForeignKeyConstraint" Type="ForeignKey" Parent="Table" />
|
||||
<Node Name="SqlDefaultConstraint" Parent="Column" Collection="False" />
|
||||
<Node Name="SqlDmlTrigger" Type="Trigger" Parent="Table" />
|
||||
<Node Name="SqlFullTextIndex" Parent="Table" Collection="False" />
|
||||
<Node Name="SqlStatistic" Parent="TableViewBase"/>
|
||||
|
||||
<Node Name="SqlDatabaseDdlTrigger" Type="Trigger" Parent="Database"/>
|
||||
<Node Name="SqlAssembly" Type="SqlAssembly" Parent="Database" >
|
||||
<NavigationPath Parent="Database" Field="Assemblies" />
|
||||
</Node>
|
||||
|
||||
<Node Name="SqlRule" Parent="Database" />
|
||||
<Node Name="SqlDefault" Parent="Database" />
|
||||
<Node Name="SqlSequence" Parent="Database" />
|
||||
|
||||
<Node Name="SqlSystemDataType" Parent="Server" />
|
||||
<Node Name="SqlUserDefinedDataType" Parent="Database" />
|
||||
|
||||
<Node Name="SqlUserDefinedTableType" Parent="Database" />
|
||||
<Node Name="SqlXmlSchemaCollection" />
|
||||
<Node Name="SqlUserDefinedType" />
|
||||
|
||||
<Node Name="SqlUserDefinedFunction" />
|
||||
|
||||
<Node Name="SqlUserDefinedAggregate" />
|
||||
|
||||
<Node Name="SqlFileGroup" />
|
||||
<Node Name="SqlFile" Type="DataFile" Parent="FileGroup" >
|
||||
<NavigationPath Parent="FileGroup" Field="Files" />
|
||||
</Node>
|
||||
|
||||
<Node Name="SqlFullTextCatalog"/>
|
||||
<Node Name="SqlFullTextStopList" />
|
||||
<Node Name="SqlPartitionFunction"/>
|
||||
<Node Name="SqlPartitionScheme"/>
|
||||
<Node Name="SqlSearchPropertyList" />
|
||||
<Node Name="SqlUser"/>
|
||||
<Node Name="SqlSchema"/>
|
||||
<Node Name="SqlAsymmetricKey" />
|
||||
<Node Name="SqlCertificate" />
|
||||
<Node Name="SqlSymmetricKey" />
|
||||
<Node Name="SqlDatabaseEncryptionKey" Collection="False" />
|
||||
<Node Name="SqlMasterKey" Collection="False" />
|
||||
<Node Name="SqlDatabaseAuditSpecification" />
|
||||
<Node Name="SqlSecurityPolicy" >
|
||||
<NavigationPath Parent="Database" Field="SecurityPolicies" />
|
||||
</Node>
|
||||
<Node Name="SqlDatabaseCredential" Type="DatabaseScopedCredential"/>
|
||||
<Node Name="SqlRole" Type="DatabaseRole" >
|
||||
<NavigationPath Parent="Database" Field="Roles" />
|
||||
</Node>
|
||||
<Node Name="SqlApplicationRole" />
|
||||
<Node Name="SqlColumnMasterKey" />
|
||||
<Node Name="SqlColumnEncryptionKey" />
|
||||
|
||||
<Node Name="SqlServiceBroker" Type="ServiceBroker" Collection="False" />
|
||||
<Node Name="SqlService" Type="BrokerService" Parent="ServiceBroker" >
|
||||
<NavigationPath Parent="ServiceBroker" Field="Services" />
|
||||
</Node>
|
||||
<Node Name="SqlContract" Type="ServiceContract" Parent="ServiceBroker" />
|
||||
<Node Name="SqlQueue" Type="ServiceQueue" Parent="ServiceBroker" >
|
||||
<NavigationPath Parent="ServiceBroker" Field="Queues" />
|
||||
</Node>
|
||||
<Node Name="SqlRemoteServiceBinding" Parent="ServiceBroker" />
|
||||
<Node Name="SqlBrokerPriority" Parent="ServiceBroker" >
|
||||
<NavigationPath Parent="ServiceBroker" Field="Priorities" />
|
||||
</Node>
|
||||
|
||||
<Node Name="SqlMessageType" Parent="ServiceBroker"/>
|
||||
|
||||
<Node Name="SqlExternalDataSource" />
|
||||
<Node Name="SqlExternalFileFormat" />
|
||||
|
||||
<Node Name="SqlProcedure" Type="StoredProcedure"/>
|
||||
<Node Name="SqlExtendedStoredProcedure" />
|
||||
<Node Name="SqlSubroutineParameter" Type="Parameter" >
|
||||
<Parent>StoredProcedure</Parent>
|
||||
<Parent>UserDefinedAggregate</Parent>
|
||||
<Parent>UserDefinedFunction</Parent>
|
||||
</Node>
|
||||
|
||||
<Node Name="SqlPartitionFunctionParameter" Parent="PartitionFunction" />
|
||||
|
||||
<Node Name="SqlBuiltInType" Type="SystemDataType" Parent="Server"/>
|
||||
<!-- TODO Enable all types
|
||||
<Node Name="SqlRoute"/>
|
||||
-->
|
||||
<!-- Signatures appear to be missing entirely from SMO and SSMS object explorer...
|
||||
<Node Name="SqlSignature" />
|
||||
-->
|
||||
<!-- TODO find mapping - exists in SSDT but not SSMS / SMO?
|
||||
<Node Name="SqlEventNotification" Parent="ServiceBroker" />
|
||||
-->
|
||||
<!-- TODO Requires XEvents SMO DLL in .Net Core
|
||||
<Node Name="SqlEventSession" Type="Session" />
|
||||
<Node Name="SqlServerEventNotification" Type="Event" Parent="Server" />
|
||||
-->
|
||||
</SmoQueryModel>
|
||||
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// 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 Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
/// <summary>
|
||||
/// A Node in the tree representing a SMO-based object
|
||||
/// </summary>
|
||||
public class SmoTreeNode : TreeNode
|
||||
{
|
||||
public static int FolderSortPriority = 0;
|
||||
private static int _nextSortPriority = FolderSortPriority + 1; // 0 is reserved for folders
|
||||
|
||||
protected SmoQueryContext context;
|
||||
|
||||
public SmoTreeNode() : base()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnInitialize()
|
||||
{
|
||||
// TODO setup initialization
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is this a system (MSShipped) object?
|
||||
/// </summary>
|
||||
public bool IsMsShippedOwned { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates which platforms a node is valid for
|
||||
/// </summary>
|
||||
public ValidForFlag ValidFor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets an incrementing sort priority value to assist in automatically sorting
|
||||
/// elements in a tree
|
||||
/// </summary>
|
||||
public static int NextSortPriority
|
||||
{
|
||||
get
|
||||
{
|
||||
return System.Threading.Interlocked.Increment(ref _nextSortPriority);
|
||||
}
|
||||
}
|
||||
|
||||
public NamedSmoObject SmoObject { get; private set; }
|
||||
|
||||
public virtual void CacheInfoFromModel(NamedSmoObject smoObject)
|
||||
{
|
||||
SmoObject = smoObject;
|
||||
NodeValue = smoObject.Name;
|
||||
}
|
||||
|
||||
public virtual NamedSmoObject GetParentSmoObject()
|
||||
{
|
||||
if (SmoObject != null)
|
||||
{
|
||||
return SmoObject;
|
||||
}
|
||||
// Return the parent's object, or null if it's not set / not a SmoTreeNode
|
||||
return ParentAs<SmoTreeNode>()?.GetParentSmoObject();
|
||||
}
|
||||
|
||||
public override object GetContext()
|
||||
{
|
||||
EnsureContextInitialized();
|
||||
return context;
|
||||
}
|
||||
|
||||
protected virtual void EnsureContextInitialized()
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
SmoObjectBase smoParent = GetParentSmoObject();
|
||||
SmoQueryContext parentContext = Parent?.GetContextAs<SmoQueryContext>();
|
||||
if (smoParent != null && parentContext != null)
|
||||
{
|
||||
context = parentContext.CopyWithParent(smoParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
internal partial class SystemExactNumericsChildFactory
|
||||
{
|
||||
private static readonly HashSet<string> _exactNumerics = new HashSet<string>{
|
||||
"bit",
|
||||
"tinyint",
|
||||
"smallint",
|
||||
"int",
|
||||
"bigint",
|
||||
"numeric",
|
||||
"decimal",
|
||||
"smallmoney",
|
||||
"money"
|
||||
};
|
||||
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
|
||||
{
|
||||
NamedSmoObject smoObject = contextObject as NamedSmoObject;
|
||||
if (smoObject != null)
|
||||
{
|
||||
string name = smoObject.Name;
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return _exactNumerics.Contains(name);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
internal partial class SystemApproximateNumericsChildFactory
|
||||
{
|
||||
private static readonly HashSet<string> _approxNumerics = new HashSet<string>{
|
||||
"float",
|
||||
"real"
|
||||
};
|
||||
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
|
||||
{
|
||||
NamedSmoObject smoObject = contextObject as NamedSmoObject;
|
||||
if (smoObject != null)
|
||||
{
|
||||
string name = smoObject.Name;
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return _approxNumerics.Contains(name);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
internal partial class SystemDateAndTimesChildFactory
|
||||
{
|
||||
private static readonly HashSet<string> _dateAndTime = new HashSet<string>{
|
||||
"datetime",
|
||||
"smalldatetime",
|
||||
"date",
|
||||
"time",
|
||||
"datetimeoffset",
|
||||
"datetime2",
|
||||
};
|
||||
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
|
||||
{
|
||||
NamedSmoObject smoObject = contextObject as NamedSmoObject;
|
||||
if (smoObject != null)
|
||||
{
|
||||
string name = smoObject.Name;
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return _dateAndTime.Contains(name);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
internal partial class SystemCharacterStringsChildFactory
|
||||
{
|
||||
private static readonly HashSet<string> _characterStrings = new HashSet<string>{
|
||||
"char",
|
||||
"varchar",
|
||||
"text",
|
||||
};
|
||||
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
|
||||
{
|
||||
NamedSmoObject smoObject = contextObject as NamedSmoObject;
|
||||
if (smoObject != null)
|
||||
{
|
||||
string name = smoObject.Name;
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return _characterStrings.Contains(name);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
internal partial class SystemUnicodeCharacterStringsChildFactory
|
||||
{
|
||||
private static readonly HashSet<string> _unicodeCharacterStrings = new HashSet<string>
|
||||
{
|
||||
"nchar",
|
||||
"nvarchar",
|
||||
"ntext",
|
||||
};
|
||||
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
|
||||
{
|
||||
NamedSmoObject smoObject = contextObject as NamedSmoObject;
|
||||
if (smoObject != null)
|
||||
{
|
||||
string name = smoObject.Name;
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return _unicodeCharacterStrings.Contains(name);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
internal partial class SystemBinaryStringsChildFactory
|
||||
{
|
||||
private static readonly HashSet<string> _binaryStrings = new HashSet<string>{
|
||||
"binary",
|
||||
"varbinary",
|
||||
"image",
|
||||
};
|
||||
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
|
||||
{
|
||||
NamedSmoObject smoObject = contextObject as NamedSmoObject;
|
||||
if (smoObject != null)
|
||||
{
|
||||
string name = smoObject.Name;
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return _binaryStrings.Contains(name);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
internal partial class SystemOtherDataTypesChildFactory
|
||||
{
|
||||
private static readonly HashSet<string> _otherDataTypes = new HashSet<string>{
|
||||
"sql_variant",
|
||||
"timestamp",
|
||||
"uniqueidentifier",
|
||||
"xml",
|
||||
};
|
||||
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
|
||||
{
|
||||
NamedSmoObject smoObject = contextObject as NamedSmoObject;
|
||||
if (smoObject != null)
|
||||
{
|
||||
string name = smoObject.Name;
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return _otherDataTypes.Contains(name);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
internal partial class SystemClrDataTypesChildFactory
|
||||
{
|
||||
private static readonly HashSet<string> _clrDataTypes = new HashSet<string>{
|
||||
"hierarchyid",
|
||||
};
|
||||
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
|
||||
{
|
||||
NamedSmoObject smoObject = contextObject as NamedSmoObject;
|
||||
if (smoObject != null)
|
||||
{
|
||||
string name = smoObject.Name;
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return _clrDataTypes.Contains(name);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
internal partial class SystemSpatialDataTypesChildFactory
|
||||
{
|
||||
private static readonly HashSet<string> _spatialDataTypes = new HashSet<string>{
|
||||
"geometry",
|
||||
"geography",
|
||||
};
|
||||
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
|
||||
{
|
||||
NamedSmoObject smoObject = contextObject as NamedSmoObject;
|
||||
if (smoObject != null)
|
||||
{
|
||||
string name = smoObject.Name;
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return _spatialDataTypes.Contains(name);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,396 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ServerExplorerTree>
|
||||
<Node Name="ServerInstance" LocLabel="SR.SchemaHierarchy_ServerInstance" Image="Server">
|
||||
<Child Name="Databases"/>
|
||||
<Child Name="ServerLevelSecurity"/>
|
||||
<Child Name="ServerLevelServerObjects"/>
|
||||
</Node>
|
||||
<Node Name="Databases" LocLabel="SR.SchemaHierarchy_Databases" IsAsyncLoad="" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabase" TreeNode="DatabaseInstanceTreeNode">
|
||||
<Child Name="SystemDatabases"/>
|
||||
</Node>
|
||||
<Node Name="ServerLevelSecurity" LocLabel="SR.SchemaHierarchy_Security" BaseClass="ModelBased" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12|NotContainedUser|CanViewSecurity">
|
||||
<Child Name="ServerLevelLinkedServerLogins"/>
|
||||
<Child Name="ServerLevelLogins"/>
|
||||
<Child Name="ServerLevelServerRoles"/>
|
||||
<Child Name="ServerLevelCredentials"/>
|
||||
<Child Name="ServerLevelCryptographicProviders"/>
|
||||
<Child Name="ServerLevelServerAudits"/>
|
||||
<Child Name="ServerLevelServerAuditSpecifications"/>
|
||||
<!-- TODO Support XEvents in .Net Core SMO
|
||||
<Child Name="ServerLevelEventSessions"/>
|
||||
-->
|
||||
</Node>
|
||||
<Node Name="ServerLevelServerObjects" LocLabel="SR.SchemaHierarchy_ServerObjects" BaseClass="ModelBased" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|NotContainedUser">
|
||||
<Child Name="ServerLevelEndpoints"/>
|
||||
<Child Name="ServerLevelLinkedServers"/>
|
||||
<Child Name="ServerLevelServerTriggers"/>
|
||||
<Child Name="ServerLevelErrorMessages"/>
|
||||
<!-- TODO Support XEvents in .Net Core SMO
|
||||
<Child Name="ServerLevelEventNotifications"/>
|
||||
-->
|
||||
</Node>
|
||||
|
||||
<Node Name="SystemDatabases" LocLabel="SR.SchemaHierarchy_SystemDatabases" BaseClass="Databases" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12|NotContainedUser|CanConnectToMaster"/>
|
||||
<!-- TODO Support XEvents in .Net Core SMO
|
||||
<Node Name="ServerLevelEventSessions" LocLabel="SR.SchemaHierarchy_EventSessions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlEventSession" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
<Node Name="ServerLevelEventNotifications" LocLabel="SR.SchemaHierarchy_ServerEventNotifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerEventNotification"/>
|
||||
-->
|
||||
|
||||
<Node Name="ServerLevelLinkedServerLogins" LocLabel="SR.SchemaHierarchy_LinkedServerLogins" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlLinkedServerLogin" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
<Node Name="ServerLevelLogins" LocLabel="SR.SchemaHierarchy_Logins" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlLogin"/>
|
||||
<Node Name="ServerLevelServerRoles" LocLabel="SR.SchemaHierarchy_ServerRoles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerRole" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
<Node Name="ServerLevelCredentials" LocLabel="SR.SchemaHierarchy_Credentials" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlCredential" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
<Node Name="ServerLevelCryptographicProviders" LocLabel="SR.SchemaHierarchy_CryptographicProviders" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlCryptographicProvider" ValidFor="Sql2008|Sql2012|Sql2014|NotDebugInstance|Sql2016|SqlvNext"/>
|
||||
<Node Name="ServerLevelServerAudits" LocLabel="SR.SchemaHierarchy_ServerAudits" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerAudit" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
<Node Name="ServerLevelServerAuditSpecifications" LocLabel="SR.SchemaHierarchy_ServerAuditSpecifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerAuditSpecification" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
|
||||
<Node Name="ServerLevelEndpoints" LocLabel="SR.SchemaHierarchy_Endpoints" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlEndpoint" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
<Node Name="ServerLevelLinkedServers" LocLabel="SR.SchemaHierarchy_LinkedServers" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlLinkedServer"/>
|
||||
<Node Name="ServerLevelServerTriggers" LocLabel="SR.SchemaHierarchy_ServerTriggers" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerDdlTrigger"/>
|
||||
<Node Name="ServerLevelErrorMessages" LocLabel="SR.SchemaHierarchy_ErrorMessages" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlErrorMessage"/>
|
||||
|
||||
<Node Name="DatabaseInstance" LocLabel="string.Empty" Image="Database" BaseClass="ModelBased" IsAsyncLoad="" Strategy="CreateModel">
|
||||
<Child Name="Tables"/>
|
||||
<Child Name="Views"/>
|
||||
<Child Name="Synonyms"/>
|
||||
<Child Name="Programmability"/>
|
||||
<Child Name="ExternalResources"/>
|
||||
<Child Name="ServiceBroker"/>
|
||||
<Child Name="Storage"/>
|
||||
<Child Name="Security"/>
|
||||
</Node>
|
||||
|
||||
<Node Name="Tables" LocLabel="SR.SchemaHierarchy_Tables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableInstanceTreeNode">
|
||||
<Filters>
|
||||
<Filter Property="IsFileTable" Value="0" Type="bool" />
|
||||
<Filter Property="IsExternal" Value="0" Type="bool" ValidFor="Sql2016|SqlvNext|AzureV12"/>
|
||||
<Filter Property="TemporalType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
|
||||
<Value>TemporalTableType.None</Value>
|
||||
<Value>TemporalTableType.SystemVersioned</Value>
|
||||
</Filter>
|
||||
</Filters>
|
||||
<Child Name="SystemTables"/>
|
||||
<Child Name="FileTables"/>
|
||||
<Child Name="ExternalTables"/>
|
||||
</Node>
|
||||
|
||||
<Node Name="Views" LocLabel="SR.SchemaHierarchy_Views" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlView" TreeNode="ViewInstanceTreeNode">
|
||||
<Child Name="SystemViews"/>
|
||||
</Node>
|
||||
|
||||
<Node Name="Synonyms" LocLabel="SR.SchemaHierarchy_Synonyms" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSynonym"/>
|
||||
<Node Name="Programmability" LocLabel="SR.SchemaHierarchy_Programmability" BaseClass="ModelBased">
|
||||
<Child Name="StoredProcedures"/>
|
||||
<Child Name="Functions"/>
|
||||
<Child Name="DatabaseTriggers"/>
|
||||
<Child Name="Assemblies"/>
|
||||
<Child Name="Types"/>
|
||||
<Child Name="Rules"/>
|
||||
<Child Name="Defaults"/>
|
||||
<Child Name="Sequences"/>
|
||||
</Node>
|
||||
<Node Name="ExternalResources" LocLabel="SR.SchemaHierarchy_ExternalResources" BaseClass="ModelBased" TreeNode="ExternalResourceInstanceTreeNode" ValidFor="Sql2016|SqlvNext|AzureV12">
|
||||
<Child Name="ExternalDataSources"/>
|
||||
<Child Name="ExternalFileFormats"/>
|
||||
</Node>
|
||||
<Node Name="ServiceBroker" LocLabel="SR.SchemaHierarchy_ServiceBroker" BaseClass="ModelBased" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext">
|
||||
<Child Name="MessageTypes"/>
|
||||
<Child Name="Contracts"/>
|
||||
<Child Name="Queues"/>
|
||||
<Child Name="Services"/>
|
||||
<!-- <Child Name="Routes"/> -->
|
||||
<Child Name="DatabaseAndQueueEventNotifications"/>
|
||||
<Child Name="RemoteServiceBindings"/>
|
||||
<Child Name="BrokerPriorities"/>
|
||||
</Node>
|
||||
|
||||
<Node Name="Storage" LocLabel="SR.SchemaHierarchy_Storage" BaseClass="ModelBased" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12">
|
||||
<Child Name="FileGroups"/>
|
||||
<Child Name="FullTextCatalogs"/>
|
||||
<Child Name="FullTextStopLists"/>
|
||||
<Child Name="SqlLogFiles"/>
|
||||
<Child Name="PartitionFunctions"/>
|
||||
<Child Name="PartitionSchemes"/>
|
||||
<Child Name="SearchPropertyLists"/>
|
||||
</Node>
|
||||
<Node Name="Security" LocLabel="SR.SchemaHierarchy_Security" BaseClass="ModelBased" >
|
||||
<Child Name="Users"/>
|
||||
<Child Name="Roles"/>
|
||||
<Child Name="Schemas"/>
|
||||
<Child Name="AsymmetricKeys"/>
|
||||
<Child Name="Certificates"/>
|
||||
<Child Name="SymmetricKeys"/>
|
||||
<Child Name="DatabaseScopedCredentials"/>
|
||||
<Child Name="DatabaseEncryptionKeys"/>
|
||||
<Child Name="MasterKeys"/>
|
||||
<Child Name="Signatures"/>
|
||||
<Child Name="DatabaseAuditSpecifications"/>
|
||||
<Child Name="SecurityPolicies"/>
|
||||
<Child Name="AlwaysEncryptedKeys"/>
|
||||
</Node>
|
||||
|
||||
<!-- Childs of Tables -->
|
||||
<Node Name="SystemTables" LocLabel="SR.SchemaHierarchy_SystemTables" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableInstanceTreeNode"/>
|
||||
<Node Name="FileTables" LocLabel="SR.SchemaHierarchy_FileTables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableInstanceTreeNode" ValidFor="Sql2012|Sql2014|Sql2016|SqlvNext|NotDebugInstance">
|
||||
<Filters>
|
||||
<Filter Property="IsFileTable" Value="1" Type="boolean" />
|
||||
</Filters>
|
||||
</Node>
|
||||
<Node Name="ExternalTables" LocLabel="SR.SchemaHierarchy_ExternalTables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="ExternalTableInstanceTreeNode" ValidFor="Sql2016|SqlvNext|AzureV12">
|
||||
<Filters>
|
||||
<Filter Property="IsExternalTable" Value="1" Type="boolean" />
|
||||
</Filters>
|
||||
</Node>
|
||||
|
||||
<Node Name="TableInstance" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="HistoryTableInstanceTreeNode">
|
||||
<!-- TODO Add special history table handling to only return related history table instead of all! Under Table, we directly show any related history tables.-->
|
||||
<Filters>
|
||||
<Filter Property="TemporalType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
|
||||
<Value>TemporalTableType.History</Value>
|
||||
</Filter>
|
||||
</Filters>
|
||||
<Child Name="Columns"/>
|
||||
<Child Name="Keys"/>
|
||||
<Child Name="Constraints"/>
|
||||
<Child Name="Triggers"/>
|
||||
<Child Name="Indexes"/>
|
||||
<Child Name="Statistics"/>
|
||||
</Node>
|
||||
|
||||
<!-- TODO This should use display item not ChildQuerierTypes -->
|
||||
<Node Name="HistoryTableInstance" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="PopulateDetails" ChildQuerierTypes="SqlTable" ValidFor="Sql2016|SqlvNext|AzureV12">
|
||||
<Child Name="Columns"/>
|
||||
<Child Name="Indexes"/>
|
||||
<Child Name="Statistics"/>
|
||||
</Node>
|
||||
|
||||
<!-- TODO This should use display item not ChildQuerierTypes -->
|
||||
<Node Name="ExternalTableInstance" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="PopulateDetails" ChildQuerierTypes="SqlTable" ValidFor="Sql2016|SqlvNext|AzureV12">
|
||||
<Child Name="Columns"/>
|
||||
<Child Name="Statistics"/>
|
||||
</Node>
|
||||
|
||||
<Node Name="Columns" LocLabel="SR.SchemaHierarchy_Columns" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlColumn" DisableSort=""/>
|
||||
<Node Name="Keys" LocLabel="SR.SchemaHierarchy_Keys" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlIndex;SqlForeignKeyConstraint" >
|
||||
<Filters>
|
||||
<Filter TypeToReverse="SqlIndex" Property="IndexKeyType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
|
||||
<Value>IndexKeyType.DriPrimaryKey</Value>
|
||||
<Value>IndexKeyType.DriUniqueKey</Value>
|
||||
</Filter>
|
||||
</Filters>
|
||||
</Node>
|
||||
<Node Name="Constraints" LocLabel="SR.SchemaHierarchy_Constraints" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlDefaultConstraint;SqlCheck"/>
|
||||
<Node Name="Triggers" LocLabel="SR.SchemaHierarchy_Triggers" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlDmlTrigger"/>
|
||||
<Node Name="Indexes" LocLabel="SR.SchemaHierarchy_Indexes" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlIndex;SqlFullTextIndex">
|
||||
<Filters>
|
||||
<Filter TypeToReverse="SqlIndex" Property="IndexKeyType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
|
||||
<Value>IndexKeyType.None</Value>
|
||||
</Filter>
|
||||
</Filters>
|
||||
</Node>
|
||||
<Node Name="Statistics" LocLabel="SR.SchemaHierarchy_Statistics" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlStatistic"/>
|
||||
|
||||
<Node Name="SystemViews" LocLabel="SR.SchemaHierarchy_SystemViews" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlView" TreeNode="ViewInstanceTreeNode"/>
|
||||
|
||||
<Node Name="ViewInstance" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="PopulateDetails">
|
||||
<Child Name="Columns"/>
|
||||
<Child Name="Triggers"/>
|
||||
<Child Name="Indexes"/>
|
||||
<Child Name="Statistics"/>
|
||||
</Node>
|
||||
|
||||
<Node Name="Functions" LocLabel="SR.SchemaHierarchy_Functions" BaseClass="ModelBased" >
|
||||
<Child Name="TableValuedFunctions"/>
|
||||
<Child Name="ScalarValuedFunctions"/>
|
||||
<Child Name="AggregateFunctions"/>
|
||||
</Node>
|
||||
<Node Name="DatabaseTriggers" LocLabel="SR.SchemaHierarchy_DatabaseTriggers" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseDdlTrigger"/>
|
||||
<Node Name="Assemblies" LocLabel="SR.SchemaHierarchy_Assemblies" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlAssembly" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
|
||||
<Node Name="Types" LocLabel="SR.SchemaHierarchy_Types" BaseClass="ModelBased" >
|
||||
<Child Name="SystemDataTypes"/>
|
||||
<Child Name="UserDefinedDataTypes"/>
|
||||
<Child Name="UserDefinedTableTypes"/>
|
||||
<Child Name="UserDefinedTypes"/>
|
||||
<Child Name="XmlSchemaCollections"/>
|
||||
</Node>
|
||||
<Node Name="Rules" LocLabel="SR.SchemaHierarchy_Rules" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRule" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
|
||||
<Node Name="Defaults" LocLabel="SR.SchemaHierarchy_Defaults" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDefault" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
|
||||
<Node Name="Sequences" LocLabel="SR.SchemaHierarchy_Sequences" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSequence" ValidFor="Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
|
||||
|
||||
<Node Name="SystemDataTypes" LocLabel="SR.SchemaHierarchy_SystemDataTypes" BaseClass="ModelBased" >
|
||||
<Child Name="SystemExactNumerics"/>
|
||||
<Child Name="SystemApproximateNumerics"/>
|
||||
<Child Name="SystemDateAndTimes"/>
|
||||
<Child Name="SystemCharacterStrings"/>
|
||||
<Child Name="SystemUnicodeCharacterStrings"/>
|
||||
<Child Name="SystemBinaryStrings"/>
|
||||
<Child Name="SystemOtherDataTypes"/>
|
||||
<Child Name="SystemClrDataTypes"/>
|
||||
<Child Name="SystemSpatialDataTypes"/>
|
||||
</Node>
|
||||
<Node Name="UserDefinedDataTypes" LocLabel="SR.SchemaHierarchy_UserDefinedDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedDataType"/>
|
||||
<Node Name="UserDefinedTableTypes" LocLabel="SR.SchemaHierarchy_UserDefinedTableTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedTableType" TreeNode="UserDefinedTableTypeInstanceTreeNode" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12"/>
|
||||
<Node Name="UserDefinedTypes" LocLabel="SR.SchemaHierarchy_UserDefinedTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedType" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
|
||||
<Node Name="XmlSchemaCollections" LocLabel="SR.SchemaHierarchy_XMLSchemaCollections" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlXmlSchemaCollection" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
|
||||
|
||||
<Node Name="UserDefinedTableTypeInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
|
||||
<Child Name="UserDefinedTableTypeColumns"/>
|
||||
<Child Name="UserDefinedTableTypeKeys"/>
|
||||
<Child Name="UserDefinedTableTypeConstraints"/>
|
||||
</Node>
|
||||
<Node Name="UserDefinedTableTypeColumns" LocLabel="SR.SchemaHierarchy_Columns" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlColumn" DisableSort=""/>
|
||||
<Node Name="UserDefinedTableTypeKeys" LocLabel="SR.SchemaHierarchy_Keys" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlIndex">
|
||||
<Filters>
|
||||
<Filter TypeToReverse="SqlIndex" Property="IndexKeyType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
|
||||
<Value>IndexKeyType.DriPrimaryKey</Value>
|
||||
<Value>IndexKeyType.DriUniqueKey</Value>
|
||||
</Filter>
|
||||
</Filters>
|
||||
</Node>
|
||||
<Node Name="UserDefinedTableTypeConstraints" LocLabel="SR.SchemaHierarchy_Constraints" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlDefaultConstraint;SqlCheck"/>/>
|
||||
|
||||
<Node Name="SystemExactNumerics" LocLabel="SR.SchemaHierarchy_SystemExactNumerics" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
|
||||
<Node Name="SystemApproximateNumerics" LocLabel="SR.SchemaHierarchy_SystemApproximateNumerics" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
|
||||
<Node Name="SystemDateAndTimes" LocLabel="SR.SchemaHierarchy_SystemDateAndTime" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
|
||||
<Node Name="SystemCharacterStrings" LocLabel="SR.SchemaHierarchy_SystemCharacterStrings" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
|
||||
<Node Name="SystemUnicodeCharacterStrings" LocLabel="SR.SchemaHierarchy_SystemUnicodeCharacterStrings" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
|
||||
<Node Name="SystemBinaryStrings" LocLabel="SR.SchemaHierarchy_SystemBinaryStrings" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
|
||||
<Node Name="SystemOtherDataTypes" LocLabel="SR.SchemaHierarchy_SystemOtherDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
|
||||
<Node Name="SystemClrDataTypes" LocLabel="SR.SchemaHierarchy_SystemCLRDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedType" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12"/>
|
||||
<Node Name="SystemSpatialDataTypes" LocLabel="SR.SchemaHierarchy_SystemSpatialDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedType" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12"/>
|
||||
|
||||
<!-- Childs of ExternalResources -->
|
||||
<Node Name="ExternalDataSources" LocLabel="SR.SchemaHierarchy_ExternalDataSources" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlExternalDataSource" ValidFor="Sql2016|SqlvNext|AzureV12"/>
|
||||
<Node Name="ExternalFileFormats" LocLabel="SR.SchemaHierarchy_ExternalFileFormats" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlExternalFileFormat" ValidFor="Sql2016|SqlvNext"/>
|
||||
|
||||
<Node Name="StoredProcedures" LocLabel="SR.SchemaHierarchy_StoredProcedures" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlProcedure" TreeNode="StoredProcedureInstanceTreeNode">
|
||||
<Child Name="SystemStoredProcedures"/>
|
||||
</Node>
|
||||
<Node Name="SystemStoredProcedures" LocLabel="SR.SchemaHierarchy_SystemStoredProcedures" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlProcedure" TreeNode="StoredProcedureInstanceTreeNode"/>
|
||||
<Node Name="StoredProcedureInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
|
||||
<Child Name="StoredProcedureParameters"/>
|
||||
</Node>
|
||||
<Node Name="StoredProcedureParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" Strategy="StoredProcedureParameters" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
|
||||
|
||||
<Node Name="TableValuedFunctions" LocLabel="SR.SchemaHierarchy_TableValuedFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedFunction" TreeNode="TableValuedFunctionInstanceTreeNode">
|
||||
<Filters>
|
||||
<Filter Property="UserDefinedFunctionType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
|
||||
<Value>UserDefinedFunctionType.Table</Value>
|
||||
</Filter>
|
||||
</Filters>
|
||||
</Node>
|
||||
<Node Name="TableValuedFunctionInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
|
||||
<Child Name="TableValuedFunctionParameters"/>
|
||||
</Node>
|
||||
<Node Name="TableValuedFunctionParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" Strategy="FunctionParameters" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
|
||||
|
||||
<Node Name="ScalarValuedFunctions" LocLabel="SR.SchemaHierarchy_ScalarValuedFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedFunction" TreeNode="ScalarValuedFunctionInstanceTreeNode" >
|
||||
<Filters>
|
||||
<Filter Property="UserDefinedFunctionType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
|
||||
<Value>UserDefinedFunctionType.Table</Value>
|
||||
</Filter>
|
||||
</Filters>
|
||||
</Node>
|
||||
<Node Name="ScalarValuedFunctionInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
|
||||
<Child Name="ScalarValuedFunctionParameters"/>
|
||||
</Node>
|
||||
<Node Name="ScalarValuedFunctionParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" Strategy="FunctionParameters" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
|
||||
|
||||
<Node Name="AggregateFunctions" LocLabel="SR.SchemaHierarchy_AggregateFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedAggregate" TreeNode="AggregateFunctionInstanceTreeNode" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
|
||||
<Node Name="AggregateFunctionInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
|
||||
<Child Name="AggregateFunctionParameters"/>
|
||||
</Node>
|
||||
<Node Name="AggregateFunctionParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
|
||||
|
||||
<!-- TODO Support Route in SMO
|
||||
<Node Name="Routes" LocLabel="SR.SchemaHierarchy_Routes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRoute"/>
|
||||
-->
|
||||
<!-- TODO support events
|
||||
<Node Name="DatabaseAndQueueEventNotifications" LocLabel="SR.SchemaHierarchy_EventNotifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlEventNotification"/>
|
||||
-->
|
||||
<Node Name="RemoteServiceBindings" LocLabel="SR.SchemaHierarchy_RemoteServiceBindings" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRemoteServiceBinding"/>
|
||||
<Node Name="BrokerPriorities" LocLabel="SR.SchemaHierarchy_BrokerPriorities" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBrokerPriority" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
|
||||
<Node Name="FileGroups" LocLabel="SR.SchemaHierarchy_FileGroups" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFileGroup" TreeNode="FileGroupInstanceTreeNode"/>
|
||||
<Node Name="FullTextCatalogs" LocLabel="SR.SchemaHierarchy_FullTextCatalogs" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFullTextCatalog"/>
|
||||
<Node Name="FullTextStopLists" LocLabel="SR.SchemaHierarchy_FullTextStopLists" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFullTextStopList" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
|
||||
<Node Name="SqlLogFiles" LocLabel="SR.SchemaHierarchy_LogFiles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFile"/>
|
||||
<Node Name="PartitionFunctions" LocLabel="SR.SchemaHierarchy_PartitionFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlPartitionFunction"/>
|
||||
<Node Name="PartitionSchemes" LocLabel="SR.SchemaHierarchy_PartitionSchemes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlPartitionScheme"/>
|
||||
<Node Name="SearchPropertyLists" LocLabel="SR.SchemaHierarchy_SearchPropertyLists" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSearchPropertyList" ValidFor="Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
|
||||
|
||||
<Node Name="FileGroupInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="">
|
||||
<Child Name="FileGroupFiles"/>
|
||||
</Node>
|
||||
|
||||
<Node Name="FileGroupFiles" LocLabel="SR.SchemaHierarchy_FilegroupFiles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFile" >
|
||||
</Node>
|
||||
|
||||
<Node Name="Users" LocLabel="SR.SchemaHierarchy_Users" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUser"/>
|
||||
<Node Name="Roles" LocLabel="SR.SchemaHierarchy_Roles" BaseClass="ModelBased" >
|
||||
<Child Name="DatabaseRoles"/>
|
||||
<Child Name="ApplicationRoles"/>
|
||||
</Node>
|
||||
<Node Name="Schemas" LocLabel="SR.SchemaHierarchy_Schemas" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSchema"/>
|
||||
<Node Name="AsymmetricKeys" LocLabel="SR.SchemaHierarchy_AsymmetricKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlAsymmetricKey" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
<Node Name="Certificates" LocLabel="SR.SchemaHierarchy_Certificates" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlCertificate" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
<Node Name="SymmetricKeys" LocLabel="SR.SchemaHierarchy_SymmetricKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSymmetricKey" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
<Node Name="DatabaseEncryptionKeys" LocLabel="SR.SchemaHierarchy_DatabaseEncryptionKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseEncryptionKey" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
<Node Name="MasterKeys" LocLabel="SR.SchemaHierarchy_MasterKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlMasterKey" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
|
||||
<!-- TODO Support signatures
|
||||
<Node Name="Signatures" LocLabel="SR.SchemaHierarchy_Signatures" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSignature" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
-->
|
||||
<Node Name="DatabaseAuditSpecifications" LocLabel="SR.SchemaHierarchy_DatabaseAuditSpecifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseAuditSpecification" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
|
||||
<Node Name="SecurityPolicies" LocLabel="SR.SchemaHierarchy_SecurityPolicies" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSecurityPolicy" ValidFor="Sql2016|SqlvNext|AzureV12"/>
|
||||
<Node Name="DatabaseScopedCredentials" LocLabel="SR.SchemaHierarchy_DatabaseScopedCredentials" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseCredential" ValidFor="Sql2016|SqlvNext|AzureV12"/>
|
||||
<Node Name="AlwaysEncryptedKeys" LocLabel="SR.SchemaHierarchy_AlwaysEncryptedKeys" BaseClass="ModelBased" ValidFor="Sql2016|SqlvNext|AzureV12">
|
||||
<Child Name="ColumnMasterKeys"/>
|
||||
<Child Name="ColumnEncryptionKeys"/>
|
||||
</Node>
|
||||
|
||||
<Node Name="DatabaseRoles" LocLabel="SR.SchemaHierarchy_DatabaseRoles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRole"/>
|
||||
<Node Name="ApplicationRoles" LocLabel="SR.SchemaHierarchy_ApplicationRoles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlApplicationRole" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
|
||||
<Node Name="ColumnMasterKeys" LocLabel="SR.SchemaHierarchy_ColumnMasterKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlColumnMasterKey" ValidFor="Sql2016|SqlvNext|AzureV12"/>
|
||||
<Node Name="ColumnEncryptionKeys" LocLabel="SR.SchemaHierarchy_ColumnEncryptionKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlColumnEncryptionKey" ValidFor="Sql2016|SqlvNext|AzureV12"/>
|
||||
|
||||
<Node Name="MessageTypes" LocLabel="SR.SchemaHierarchy_MessageTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlMessageType">
|
||||
<Child Name="SystemMessageTypes"/>
|
||||
</Node>
|
||||
<Node Name="SystemMessageTypes" LocLabel="SR.SchemaHierarchy_SystemMessageTypes" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlMessageType"/>
|
||||
|
||||
<Node Name="Contracts" LocLabel="SR.SchemaHierarchy_Contracts" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlContract">
|
||||
<Child Name="SystemContracts"/>
|
||||
</Node>
|
||||
<Node Name="SystemContracts" LocLabel="SR.SchemaHierarchy_SystemContracts" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlContract"/>
|
||||
|
||||
<Node Name="Queues" LocLabel="SR.SchemaHierarchy_Queues" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlQueue">
|
||||
<Child Name="SystemQueues"/>
|
||||
</Node>
|
||||
<Node Name="SystemQueues" LocLabel="SR.SchemaHierarchy_SystemQueues" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlQueue"/>
|
||||
|
||||
<Node Name="Services" LocLabel="SR.SchemaHierarchy_Services" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlService">
|
||||
<Child Name="SystemServices"/>
|
||||
</Node>
|
||||
<Node Name="SystemServices" LocLabel="SR.SchemaHierarchy_SystemServices" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlService"/>
|
||||
|
||||
<CodeGenOptions>
|
||||
<UniqueTreeNode Name="DatabaseInstanceTreeNode"/>
|
||||
<UniqueTreeNode Name="TableInstanceTreeNode"/>
|
||||
<UniqueTreeNode Name="ViewInstanceTreeNode"/>
|
||||
<UniqueTreeNode Name="UserDefinedTableTypeInstanceTreeNode"/>
|
||||
<UniqueTreeNode Name="StoredProcedureInstanceTreeNode"/>
|
||||
<UniqueTreeNode Name="TableValuedFunctionInstanceTreeNode"/>
|
||||
<UniqueTreeNode Name="ScalarValuedFunctionInstanceTreeNode"/>
|
||||
<UniqueTreeNode Name="AggregateFunctionInstanceTreeNode"/>
|
||||
<UniqueTreeNode Name="FileGroupInstanceTreeNode"/>
|
||||
<UniqueTreeNode Name="ExternalTableInstanceTreeNode"/>
|
||||
<UniqueTreeNode Name="ExternalResourceInstanceTreeNode"/>
|
||||
<UniqueTreeNode Name="HistoryTableInstanceTreeNode" />
|
||||
</CodeGenOptions>
|
||||
|
||||
<!-- WARNING: Specifying reverse dependencies that could load large numbers of objects will be detrimental to performance. -->
|
||||
<ReverseDependencyList>
|
||||
<ReverseDependency Type="SqlUser" DependsOn="SqlRole;SqlRoleMembership"/>
|
||||
</ReverseDependencyList>
|
||||
</ServerExplorerTree>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,387 @@
|
||||
<#@ template debug="false" hostspecific="true" language="C#" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Xml.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" #>
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Composition;
|
||||
using Microsoft.SqlTools.ServiceLayer;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
|
||||
<#
|
||||
var directory = Path.GetDirectoryName(Host.TemplateFile);
|
||||
string xmlFile = Path.Combine(directory, "TreeNodeDefinition.xml");
|
||||
|
||||
/////////
|
||||
// TODO - is Generate all the ReverseDependencies needed?
|
||||
/////////
|
||||
// var allReverseDependencies = GetReverseDependencies(xmlFile);
|
||||
// WriteLine(" internal static class TreeNodeRules");
|
||||
// WriteLine(" {");
|
||||
// WriteLine(" internal static Dictionary<Type, IList<Type>> TypeReverseDependencyMap = new Dictionary<Type, IList<Type>>()");
|
||||
// WriteLine(" {");
|
||||
// foreach (var reverseDependencyKey in allReverseDependencies.Keys)
|
||||
// {
|
||||
// bool isFirstDependentType = true;
|
||||
// StringBuilder dependentListBuilder = new StringBuilder("{");
|
||||
// foreach (var dependentType in allReverseDependencies[reverseDependencyKey])
|
||||
// {
|
||||
// if (isFirstDependentType)
|
||||
// {
|
||||
// isFirstDependentType = false;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// dependentListBuilder.Append(",");
|
||||
// }
|
||||
//
|
||||
// dependentListBuilder.Append(string.Format(CultureInfo.InvariantCulture, " typeof({0})", dependentType));
|
||||
// }
|
||||
// dependentListBuilder.Append(" }");
|
||||
//
|
||||
// WriteLine(string.Format(CultureInfo.InvariantCulture, " {{ typeof({0}), new List<Type> {1} }}", reverseDependencyKey, dependentListBuilder.ToString()));
|
||||
// }
|
||||
// WriteLine(" };");
|
||||
// WriteLine(" }");
|
||||
// WriteLine("");
|
||||
|
||||
/////////
|
||||
// First generate all the TreeNodes
|
||||
/////////
|
||||
var allTreeNodes = GetUniqueTreeNodes(xmlFile);
|
||||
foreach (var TreeNode in allTreeNodes)
|
||||
{
|
||||
var name = TreeNode.GetAttribute("Name");
|
||||
WriteLine(string.Format(" internal sealed partial class {0} : SmoTreeNode", name));
|
||||
WriteLine(" {");
|
||||
WriteLine(string.Format(" public {0}() : base()", name));
|
||||
WriteLine(" {");
|
||||
WriteLine(" NodeValue = string.Empty;");
|
||||
WriteLine(string.Format(" this.NodeType = \"{0}\";", name.Replace("TreeNode", string.Empty)));
|
||||
WriteLine(string.Format(" this.NodeTypeId = NodeTypes.{0};", name.Replace("TreeNode", string.Empty)));
|
||||
WriteLine(" OnInitialize();");
|
||||
WriteLine(" }");
|
||||
WriteLine(" }");
|
||||
WriteLine("");
|
||||
}
|
||||
|
||||
/////////
|
||||
// Now generate all the ChildFactories
|
||||
/////////
|
||||
var allNodes = GetNodes(xmlFile);
|
||||
foreach (var type in allNodes)
|
||||
{
|
||||
XmlElement nodeElement = GetNodeElement(xmlFile, type);
|
||||
var imageAttr = nodeElement.GetAttribute("Image");
|
||||
var isAlwaysLeaf = nodeElement.GetAttributeNode("IsAlwaysLeaf");
|
||||
var baseClass = nodeElement.GetAttribute("BaseClass");
|
||||
var strategy = nodeElement.GetAttribute("Strategy");
|
||||
var ChildQuerierTypes = nodeElement.GetAttribute("ChildQuerierTypes");
|
||||
var TreeNode = nodeElement.GetAttribute("TreeNode");
|
||||
var isAsync = nodeElement.GetAttributeNode("IsAsyncLoad");
|
||||
var disableSort = nodeElement.GetAttributeNode("DisableSort");
|
||||
|
||||
string childFactoryBaseClass = "SmoChildFactoryBase";
|
||||
|
||||
// TODO Will we need alternative child factories? If so, add code here to support this
|
||||
|
||||
if (isAlwaysLeaf == null)
|
||||
{
|
||||
WriteLine(" [Export(typeof(ChildFactory))]");
|
||||
WriteLine(" [Shared]");
|
||||
|
||||
WriteLine(string.Format(" internal partial class {0}ChildFactory : {1}", type, childFactoryBaseClass));
|
||||
|
||||
WriteLine(" {");
|
||||
WriteLine(string.Format(" public override IEnumerable<string> ApplicableParents() {{ return new[] {{ \"{0}\" }}; }}", type));
|
||||
|
||||
List<XmlElement> children = GetChildren(xmlFile, type);
|
||||
if (children.Count > 0)
|
||||
{
|
||||
WriteLine("");
|
||||
WriteLine(" protected override void OnExpandPopulateFolders(IList<TreeNode> currentChildren, TreeNode parent)");
|
||||
WriteLine(" {");
|
||||
foreach (var child in children)
|
||||
{
|
||||
XmlElement childAsXmlElement = GetNodeElement(xmlFile, child.GetAttribute("Name"));
|
||||
if (childAsXmlElement == null)
|
||||
{
|
||||
// TODO SHould we error with clear message that this needs to be fixed?
|
||||
continue;
|
||||
}
|
||||
string childImage = childAsXmlElement.GetAttribute("Image");
|
||||
var msShippedOwned = childAsXmlElement.GetAttributeNode("IsMsShippedOwned");
|
||||
var validFor = childAsXmlElement.GetAttribute("ValidFor");
|
||||
|
||||
if (TreeNodeExists(xmlFile, child.GetAttribute("Name") + "TreeNode"))
|
||||
{
|
||||
WriteLine(string.Format(" currentChildren.Add(new {0}TreeNode {{ SortPriority = SmoTreeNode.NextSortPriority }} );", child.GetAttribute("Name")));
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine(" currentChildren.Add(new FolderNode {");
|
||||
WriteLine(string.Format(" NodeValue = {0},", childAsXmlElement.GetAttribute("LocLabel")));
|
||||
WriteLine(string.Format(" NodeType = \"{0}\",", "Folder"));
|
||||
WriteLine(string.Format(" NodeTypeId = NodeTypes.{0},", child.GetAttribute("Name")));
|
||||
|
||||
if (msShippedOwned != null)
|
||||
{
|
||||
WriteLine(" IsMsShippedOwned = true,");
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(validFor))
|
||||
{
|
||||
WriteLine(string.Format(" ValidFor = {0},", GetValidForFlags(validFor)));
|
||||
}
|
||||
WriteLine(" SortPriority = SmoTreeNode.NextSortPriority,");
|
||||
WriteLine(" });");
|
||||
}
|
||||
}
|
||||
WriteLine(" }");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(strategy))
|
||||
{
|
||||
string[] allTypes = ChildQuerierTypes.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
WriteLine("");
|
||||
WriteLine(" internal override Type[] ChildQuerierTypes");
|
||||
WriteLine(" {");
|
||||
WriteLine(" get");
|
||||
WriteLine(" {");
|
||||
if (!string.IsNullOrWhiteSpace(ChildQuerierTypes))
|
||||
{
|
||||
Write(" return new [] {");
|
||||
foreach (var typeToRe in allTypes)
|
||||
{
|
||||
Write(string.Format(" typeof({0}Querier),", typeToRe));
|
||||
}
|
||||
WriteLine(" };");
|
||||
}
|
||||
else
|
||||
{
|
||||
Write(" return new Type[0];");
|
||||
}
|
||||
WriteLine(" }");
|
||||
WriteLine(" }");
|
||||
|
||||
WriteLine("");
|
||||
|
||||
WriteLine(" public override TreeNode CreateChild(TreeNode parent, object context)");
|
||||
WriteLine(" {");
|
||||
if (string.IsNullOrWhiteSpace(TreeNode))
|
||||
{
|
||||
WriteLine(" var child = new SmoTreeNode();");
|
||||
WriteLine(" child.IsAlwaysLeaf = true;");
|
||||
}
|
||||
else
|
||||
{
|
||||
var modelNodeChildren = GetNodeElement(xmlFile, TreeNode.Replace("TreeNode",string.Empty));
|
||||
WriteLine(string.Format(" var child = new {0}();", TreeNode));
|
||||
if (modelNodeChildren.ChildNodes.Count == 0)
|
||||
{
|
||||
WriteLine(" child.IsAlwaysLeaf = true;");
|
||||
}
|
||||
}
|
||||
if (disableSort != null)
|
||||
{
|
||||
WriteLine(" child.SortPriority = SmoTreeNode.NextSortPriority;");
|
||||
}
|
||||
WriteLine(" InitializeChild(child, context);");
|
||||
WriteLine(" return child;");
|
||||
WriteLine(" }");
|
||||
}
|
||||
else if (baseClass == "ModelBased")
|
||||
{
|
||||
WriteLine("");
|
||||
WriteLine(" internal override Type[] ChildQuerierTypes { get {return null;} }");
|
||||
WriteLine("");
|
||||
// TODO Is reverse engineering strategy every needed?
|
||||
// WriteLine(" protected override ReverseEngineeringStrategy Strategy { get {return ReverseEngineeringStrategy.None;} }");
|
||||
WriteLine("");
|
||||
WriteLine(" public override TreeNode CreateChild(TreeNode parent, object context)");
|
||||
WriteLine(" {");
|
||||
WriteLine(" return null;");
|
||||
WriteLine(" }");
|
||||
}
|
||||
|
||||
WriteLine(" }");
|
||||
WriteLine("");
|
||||
}
|
||||
}
|
||||
#>
|
||||
}
|
||||
|
||||
<#+
|
||||
public static string GetValidForFlags(string validForStr)
|
||||
{
|
||||
List<string> flags = new List<string>();
|
||||
if (validForStr.Contains("Sql2005"))
|
||||
{
|
||||
flags.Add("ValidForFlag.Sql2005");
|
||||
}
|
||||
|
||||
if (validForStr.Contains("Sql2008"))
|
||||
{
|
||||
flags.Add("ValidForFlag.Sql2008");
|
||||
}
|
||||
|
||||
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("AzureV11"))
|
||||
{
|
||||
flags.Add("ValidForFlag.Azure");
|
||||
}
|
||||
|
||||
if (validForStr.Contains("AzureV12"))
|
||||
{
|
||||
flags.Add("ValidForFlag.AzureV12");
|
||||
}
|
||||
|
||||
if (validForStr.Contains("NotDebugInstance"))
|
||||
{
|
||||
flags.Add("ValidForFlag.NotDebugInstance");
|
||||
}
|
||||
|
||||
if (validForStr.Contains("NotContainedUser"))
|
||||
{
|
||||
flags.Add("ValidForFlag.NotContainedUser");
|
||||
}
|
||||
|
||||
if (validForStr.Contains("CanConnectToMaster"))
|
||||
{
|
||||
flags.Add("ValidForFlag.CanConnectToMaster");
|
||||
}
|
||||
|
||||
if (validForStr.Contains("CanViewSecurity"))
|
||||
{
|
||||
flags.Add("ValidForFlag.CanViewSecurity");
|
||||
}
|
||||
|
||||
return string.Join("|", flags);
|
||||
}
|
||||
public static string[] GetNodes(string xmlFile)
|
||||
{
|
||||
List<string> typesList = new List<string>();
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load(xmlFile);
|
||||
XmlNodeList treeTypes = doc.SelectNodes("/ServerExplorerTree/Node");
|
||||
if (treeTypes != null)
|
||||
{
|
||||
foreach (var type in treeTypes)
|
||||
{
|
||||
XmlElement element = type as XmlElement;
|
||||
if (element != null)
|
||||
{
|
||||
typesList.Add(element.GetAttribute("Name"));
|
||||
}
|
||||
}
|
||||
}
|
||||
return typesList.ToArray();
|
||||
}
|
||||
|
||||
public static Dictionary<string, List<string>> GetReverseDependencies(string xmlFile)
|
||||
{
|
||||
Dictionary<string, List<string>> dependencyMap = new Dictionary<string, List<string>>();
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load(xmlFile);
|
||||
XmlNodeList treeTypes = doc.SelectNodes("/ServerExplorerTree/ReverseDependencyList/ReverseDependency");
|
||||
if (treeTypes != null)
|
||||
{
|
||||
foreach (var type in treeTypes)
|
||||
{
|
||||
XmlElement element = type as XmlElement;
|
||||
if (element != null)
|
||||
{
|
||||
string typeName = element.GetAttribute("Type");
|
||||
string dependency = element.GetAttribute("DependsOn");
|
||||
List<string> dependenciesForType;
|
||||
if (dependencyMap.TryGetValue(typeName, out dependenciesForType))
|
||||
{
|
||||
dependenciesForType.Add(dependency);
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] allDepedencies = dependency.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
dependenciesForType = new List<string>();
|
||||
dependenciesForType.AddRange(allDepedencies);
|
||||
dependencyMap.Add(typeName, dependenciesForType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return dependencyMap;
|
||||
}
|
||||
|
||||
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 bool TreeNodeExists(string xmlFile, string TreeNode)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load(xmlFile);
|
||||
var found = (XmlElement)doc.SelectSingleNode(string.Format("/ServerExplorerTree/CodeGenOptions/UniqueTreeNode[@Name='{0}']", TreeNode));
|
||||
|
||||
return (found != null);
|
||||
}
|
||||
|
||||
public static List<XmlElement> GetUniqueTreeNodes(string xmlFile)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load(xmlFile);
|
||||
|
||||
List<XmlElement> retElements = new List<XmlElement>();
|
||||
XmlNodeList nodeList = doc.SelectNodes("/ServerExplorerTree/CodeGenOptions/UniqueTreeNode");
|
||||
foreach (var item in nodeList)
|
||||
{
|
||||
XmlElement itemAsElement = item as XmlElement;
|
||||
if (itemAsElement != null)
|
||||
{
|
||||
retElements.Add(itemAsElement);
|
||||
}
|
||||
}
|
||||
return retElements;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
#>
|
||||
Reference in New Issue
Block a user