mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
Clean up smo folder (#1059)
Co-authored-by: Monica Gupta <mogupt@microsoft.com>
This commit is contained in:
@@ -1,74 +0,0 @@
|
||||
//
|
||||
// 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 System.Threading;
|
||||
using Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel;
|
||||
using Microsoft.Kusto.ServiceLayer.DataSource.Metadata;
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="ChildFactory"/> supports creation of <see cref="TreeNode"/> children
|
||||
/// for a class of objects in the tree. The
|
||||
/// </summary>
|
||||
public abstract class ChildFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The set of applicable parents for which the factory can create children.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// the string names for each <see cref="TreeNode.NodeType"/> that
|
||||
/// this factory can create children for
|
||||
/// </returns>
|
||||
public abstract IEnumerable<string> ApplicableParents();
|
||||
|
||||
/// <summary>
|
||||
/// Expands an element in the
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent Node</param>
|
||||
/// <param name="refresh">force to refresh</param>
|
||||
/// <param name="refresh">name of the sql object to filter</param>
|
||||
/// <returns></returns>
|
||||
public abstract IEnumerable<TreeNode> Expand(TreeNode parent, bool refresh, string name, bool includeSystemObjects, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// The list of filters that should be applied on the smo object list
|
||||
/// </summary>
|
||||
public abstract IEnumerable<NodeFilter> Filters { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The list of properties to be loaded with the object
|
||||
/// </summary>
|
||||
public abstract IEnumerable<NodeSmoProperty> SmoProperties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the node sub type if the object can have sub types otehr wise returns empty string
|
||||
/// </summary>
|
||||
public abstract string GetNodeSubType(object objectMetadata, QueryContext oeContext);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the status of the object assigned to node. If the object doesn't spport status returns empty string
|
||||
/// </summary>
|
||||
public abstract string GetNodeStatus(object objectMetadata, QueryContext oeContext);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the custom name of the object assigned to the node. If the object doesn't have custom name, returns empty string
|
||||
/// </summary>
|
||||
public abstract string GetNodeCustomName(object objectMetadata, QueryContext oeContext);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the name of the object as shown in its Object Explorer node path
|
||||
/// </summary>
|
||||
public abstract string GetNodePathName(object objectMetadata);
|
||||
|
||||
public abstract bool CanCreateChild(TreeNode parent, object context); // TODOKusto: Can this context be changed to DataSourceObjectMetadata
|
||||
public abstract TreeNode CreateChild(TreeNode parent, DataSourceObjectMetadata childMetadata);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes
|
||||
{
|
||||
/// <summary>
|
||||
/// Has information for SMO object properties to be loaded with the SMO object
|
||||
/// </summary>
|
||||
public class NodeSmoProperty
|
||||
{
|
||||
/// <summary>
|
||||
/// Property name
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates which platforms a filter is valid for
|
||||
/// </summary>
|
||||
public ValidForFlag ValidFor { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes
|
||||
{
|
||||
public class TreeNodeWithContext
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@ using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlServer.Management.Common; // For ServerConnection
|
||||
using Microsoft.SqlTools.Extensibility;
|
||||
using Microsoft.SqlTools.Hosting;
|
||||
using Microsoft.SqlTools.Hosting.Protocol;
|
||||
@@ -45,7 +44,6 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer
|
||||
private ConnectionService connectionService;
|
||||
private IProtocolEndpoint _serviceHost;
|
||||
private ConcurrentDictionary<string, ObjectExplorerSession> sessionMap;
|
||||
private readonly Lazy<Dictionary<string, HashSet<ChildFactory>>> applicableNodeChildFactories;
|
||||
private IMultiServiceProvider serviceProvider;
|
||||
private string connectionName = "ObjectExplorer";
|
||||
|
||||
@@ -62,18 +60,9 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer
|
||||
{
|
||||
_connectedBindingQueue = connectedBindingQueue;
|
||||
sessionMap = new ConcurrentDictionary<string, ObjectExplorerSession>();
|
||||
applicableNodeChildFactories = new Lazy<Dictionary<string, HashSet<ChildFactory>>>(PopulateFactories);
|
||||
NodePathGenerator.Initialize();
|
||||
}
|
||||
|
||||
private Dictionary<string, HashSet<ChildFactory>> ApplicableNodeChildFactories
|
||||
{
|
||||
get
|
||||
{
|
||||
return applicableNodeChildFactories.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the session ids
|
||||
/// </summary>
|
||||
@@ -489,7 +478,7 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer
|
||||
waitForLockTimeout: timeout,
|
||||
bindOperation: (bindingContext, cancelToken) =>
|
||||
{
|
||||
session = ObjectExplorerSession.CreateSession(connectionResult, serviceProvider, bindingContext.ServerConnection, bindingContext.DataSource, isDefaultOrSystemDatabase);
|
||||
session = ObjectExplorerSession.CreateSession(connectionResult, serviceProvider, bindingContext.DataSource, isDefaultOrSystemDatabase);
|
||||
session.ConnectionInfo = connectionInfo;
|
||||
|
||||
sessionMap.AddOrUpdate(uri, session, (key, oldSession) => session);
|
||||
@@ -636,62 +625,6 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer
|
||||
internal static string GenerateUri(ConnectionDetails details)
|
||||
{
|
||||
return ConnectedBindingQueue.GetConnectionContextKey(details);
|
||||
}
|
||||
|
||||
public IEnumerable<ChildFactory> GetApplicableChildFactories(TreeNode item)
|
||||
{
|
||||
if (ApplicableNodeChildFactories != null)
|
||||
{
|
||||
HashSet<ChildFactory> applicableFactories;
|
||||
if (ApplicableNodeChildFactories.TryGetValue(item.NodeTypeId.ToString(), out applicableFactories))
|
||||
{
|
||||
return applicableFactories;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internal Dictionary<string, HashSet<ChildFactory>> PopulateFactories()
|
||||
{
|
||||
VerifyServicesInitialized();
|
||||
|
||||
var childFactories = new Dictionary<string, HashSet<ChildFactory>>();
|
||||
// Create our list of all NodeType to ChildFactory objects so we can expand appropriately
|
||||
foreach (var factory in serviceProvider.GetServices<ChildFactory>())
|
||||
{
|
||||
var parents = factory.ApplicableParents();
|
||||
if (parents != null)
|
||||
{
|
||||
foreach (var parent in parents)
|
||||
{
|
||||
AddToApplicableChildFactories(childFactories, factory, parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
return childFactories;
|
||||
}
|
||||
|
||||
private void VerifyServicesInitialized()
|
||||
{
|
||||
if (serviceProvider == null)
|
||||
{
|
||||
throw new InvalidOperationException(SqlTools.Hosting.SR.ServiceProviderNotSet);
|
||||
}
|
||||
if (connectionService == null)
|
||||
{
|
||||
throw new InvalidOperationException(SqlTools.Hosting.SR.ServiceProviderNotSet);
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddToApplicableChildFactories(Dictionary<string, HashSet<ChildFactory>> childFactories, ChildFactory factory, string parent)
|
||||
{
|
||||
HashSet<ChildFactory> applicableFactories;
|
||||
if (!childFactories.TryGetValue(parent, out applicableFactories))
|
||||
{
|
||||
applicableFactories = new HashSet<ChildFactory>();
|
||||
childFactories[parent] = applicableFactories;
|
||||
}
|
||||
applicableFactories.Add(factory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -771,7 +704,7 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer
|
||||
public ObjectExplorerSession(string uri, TreeNode root)
|
||||
{
|
||||
Validate.IsNotNullOrEmptyString("uri", uri);
|
||||
Validate.IsNotNull("root", root);
|
||||
Validate.IsNotNull("root", root);
|
||||
Uri = uri;
|
||||
Root = root;
|
||||
}
|
||||
@@ -783,23 +716,15 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer
|
||||
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
public static ObjectExplorerSession CreateSession(ConnectionCompleteParams response, IMultiServiceProvider serviceProvider, ServerConnection serverConnection, IDataSource dataSource, bool isDefaultOrSystemDatabase)
|
||||
public static ObjectExplorerSession CreateSession(ConnectionCompleteParams response, IMultiServiceProvider serviceProvider, IDataSource dataSource, bool isDefaultOrSystemDatabase)
|
||||
{
|
||||
DataSourceObjectMetadata objectMetadata = MetadataFactory.CreateClusterMetadata(dataSource.ClusterName);
|
||||
ServerNode rootNode = new ServerNode(response, serviceProvider, serverConnection, dataSource, objectMetadata);
|
||||
ServerNode rootNode = new ServerNode(response, serviceProvider, dataSource, objectMetadata);
|
||||
|
||||
var session = new ObjectExplorerSession(response.OwnerUri, rootNode);
|
||||
if (!isDefaultOrSystemDatabase)
|
||||
{
|
||||
DataSourceObjectMetadata databaseMetadata = MetadataFactory.CreateDatabaseMetadata(objectMetadata, response.ConnectionSummary.DatabaseName);
|
||||
|
||||
// Assuming the databases are in a folder under server node
|
||||
DataSourceTreeNode databaseNode = new DataSourceTreeNode(dataSource, databaseMetadata) {
|
||||
Parent = rootNode,
|
||||
NodeType = "Database",
|
||||
NodeTypeId = NodeTypes.Database
|
||||
};
|
||||
session.Root = databaseNode;
|
||||
}
|
||||
|
||||
return session;
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Composition;
|
||||
using System.Linq;
|
||||
using Microsoft.Kusto.ServiceLayer.DataSource.Metadata;
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
|
||||
{
|
||||
|
||||
// TODOKusto: Do we need the Querier. This has been short circuited in smoChildFactoryBase. There is no caller to the "Query" function.
|
||||
[Export(typeof(DataSourceQuerier))]
|
||||
internal partial class DatabaseQuerier: DataSourceQuerier
|
||||
{
|
||||
public override IEnumerable<DataSourceObjectMetadata> Query(QueryContext context, string filter, bool refresh, IEnumerable<string> extraProperties)
|
||||
{
|
||||
if (context.DataSource != null)
|
||||
{
|
||||
return context.DataSource.GetChildObjects(context.ParentObjectMetadata);
|
||||
}
|
||||
return Enumerable.Empty<DataSourceObjectMetadata>();
|
||||
}
|
||||
}
|
||||
|
||||
[Export(typeof(DataSourceQuerier))]
|
||||
internal partial class TableQuerier: DataSourceQuerier
|
||||
{
|
||||
public override IEnumerable<DataSourceObjectMetadata> Query(QueryContext context, string filter, bool refresh, IEnumerable<string> extraProperties)
|
||||
{
|
||||
if (context.ParentObjectMetadata != null)
|
||||
{
|
||||
return context.DataSource.GetChildObjects(context.ParentObjectMetadata);
|
||||
}
|
||||
return Enumerable.Empty<DataSourceObjectMetadata>();
|
||||
}
|
||||
}
|
||||
|
||||
[Export(typeof(DataSourceQuerier))]
|
||||
internal partial class ColumnQuerier: DataSourceQuerier
|
||||
{
|
||||
public override IEnumerable<DataSourceObjectMetadata> Query(QueryContext context, string filter, bool refresh, IEnumerable<string> extraProperties)
|
||||
{
|
||||
if (context.ParentObjectMetadata != null)
|
||||
{
|
||||
return context.DataSource.GetChildObjects(context.ParentObjectMetadata);
|
||||
}
|
||||
return Enumerable.Empty<DataSourceObjectMetadata>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using Microsoft.Kusto.ServiceLayer.DataSource;
|
||||
using Microsoft.Kusto.ServiceLayer.DataSource.Metadata;
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a folder node in the tree
|
||||
/// </summary>
|
||||
public class FolderNode : DataSourceTreeNode
|
||||
{
|
||||
public FolderNode(IDataSource dataSource, DataSourceObjectMetadata objectMetadata)
|
||||
: base(dataSource, objectMetadata)
|
||||
{
|
||||
}
|
||||
|
||||
/// <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="KustoMetadata"/> from this parent's parent, or null if not found</returns>
|
||||
public override DataSourceObjectMetadata GetParentObjectMetadata()
|
||||
{
|
||||
return ParentAs<DataSourceTreeNode>()?.GetParentObjectMetadata();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlTools.Extensibility;
|
||||
using Microsoft.Kusto.ServiceLayer.Connection.Contracts;
|
||||
using Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes;
|
||||
@@ -25,9 +24,8 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
|
||||
private ConnectionSummary connectionSummary;
|
||||
private ServerInfo serverInfo;
|
||||
private Lazy<QueryContext> context;
|
||||
private ServerConnection serverConnection;
|
||||
|
||||
public ServerNode(ConnectionCompleteParams connInfo, IMultiServiceProvider serviceProvider, ServerConnection serverConnection, IDataSource dataSource, DataSourceObjectMetadata objectMetadata)
|
||||
public ServerNode(ConnectionCompleteParams connInfo, IMultiServiceProvider serviceProvider, IDataSource dataSource, DataSourceObjectMetadata objectMetadata)
|
||||
: base(dataSource, objectMetadata)
|
||||
{
|
||||
Validate.IsNotNull(nameof(connInfo), connInfo);
|
||||
@@ -38,7 +36,6 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
|
||||
this.serverInfo = connInfo.ServerInfo;
|
||||
|
||||
this.context = new Lazy<QueryContext>(() => CreateContext(serviceProvider));
|
||||
this.serverConnection = serverConnection;
|
||||
|
||||
NodeValue = connectionSummary.ServerName;
|
||||
IsAlwaysLeaf = false;
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
//
|
||||
// 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.Threading;
|
||||
using Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes;
|
||||
using Microsoft.Kusto.ServiceLayer.DataSource.Metadata;
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
|
||||
{
|
||||
public class DataSourceChildFactoryBase : ChildFactory
|
||||
{
|
||||
private IEnumerable<NodeSmoProperty> smoProperties;
|
||||
public override IEnumerable<string> ApplicableParents()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override IEnumerable<TreeNode> Expand(TreeNode parent, bool refresh, string name, bool includeSystemObjects, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException(); // Moved to TreeNode.cs
|
||||
}
|
||||
|
||||
private bool ShouldFilterNode(TreeNode childNode, ValidForFlag validForFlag)
|
||||
{
|
||||
bool filterTheNode = false;
|
||||
|
||||
return filterTheNode;
|
||||
}
|
||||
|
||||
private string GetProperyFilter(IEnumerable<NodeFilter> filters, Type querierType, ValidForFlag validForFlag)
|
||||
{
|
||||
string filter = string.Empty;
|
||||
if (filters != null)
|
||||
{
|
||||
var filtersToApply = filters.Where(f => f.CanApplyFilter(querierType, validForFlag)).ToList();
|
||||
filter = string.Empty;
|
||||
if (filtersToApply.Any())
|
||||
{
|
||||
filter = NodeFilter.ConcatProperties(filtersToApply);
|
||||
}
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
private bool IsCompatibleQuerier(DataSourceQuerier 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;
|
||||
|
||||
}
|
||||
|
||||
public override bool CanCreateChild(TreeNode parent, object context)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override TreeNode CreateChild(TreeNode parent, DataSourceObjectMetadata childMetadata)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected virtual void InitializeChild(TreeNode parent, TreeNode child, object context)
|
||||
{
|
||||
DataSourceObjectMetadata objectMetadata = context as DataSourceObjectMetadata;
|
||||
if (objectMetadata == null)
|
||||
{
|
||||
Debug.WriteLine("context is not a DataSourceObjectMetadata type: " + context.GetType());
|
||||
}
|
||||
else
|
||||
{
|
||||
smoProperties = SmoProperties;
|
||||
DataSourceTreeNode childAsMeItem = (DataSourceTreeNode)child;
|
||||
childAsMeItem.CacheInfoFromModel(objectMetadata);
|
||||
QueryContext oeContext = parent.GetContextAs<QueryContext>();
|
||||
|
||||
// If node has custom name, replaced it with the name already set
|
||||
string customizedName = GetNodeCustomName(context, oeContext);
|
||||
if (!string.IsNullOrEmpty(customizedName))
|
||||
{
|
||||
childAsMeItem.NodeValue = customizedName;
|
||||
childAsMeItem.NodePathName = GetNodePathName(context);
|
||||
}
|
||||
|
||||
childAsMeItem.NodeSubType = GetNodeSubType(context, oeContext);
|
||||
childAsMeItem.NodeStatus = GetNodeStatus(context, oeContext);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual Type[] ChildQuerierTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<NodeFilter> Filters
|
||||
{
|
||||
get
|
||||
{
|
||||
return Enumerable.Empty<NodeFilter>();
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<NodeSmoProperty> SmoProperties
|
||||
{
|
||||
get
|
||||
{
|
||||
return Enumerable.Empty<NodeSmoProperty>();
|
||||
}
|
||||
}
|
||||
|
||||
internal IEnumerable<NodeSmoProperty> CachedSmoProperties
|
||||
{
|
||||
get
|
||||
{
|
||||
return smoProperties == null ? SmoProperties : smoProperties;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
|
||||
public override string GetNodeSubType(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public override string GetNodeStatus(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public static bool IsPropertySupported(string propertyName, QueryContext context, DataSourceObjectMetadata objectMetadata, IEnumerable<NodeSmoProperty> supportedProperties)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string GetNodeCustomName(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return (objectMetadata as DataSourceObjectMetadata).PrettyName;
|
||||
}
|
||||
|
||||
public override string GetNodePathName(object objectMetadata)
|
||||
{
|
||||
return (objectMetadata as DataSourceObjectMetadata).Urn;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
//
|
||||
// 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.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
|
||||
{
|
||||
/// <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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,356 +0,0 @@
|
||||
//
|
||||
// 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.Globalization;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Custom name for Columns
|
||||
/// </summary>
|
||||
internal partial class ColumnsChildFactory : DataSourceChildFactoryBase
|
||||
{
|
||||
public override string GetNodeCustomName(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return SmoColumnCustomNodeHelper.CalculateCustomLabel(objectMetadata, oeContext);
|
||||
}
|
||||
|
||||
private readonly Lazy<List<NodeSmoProperty>> smoPropertiesLazy = new Lazy<List<NodeSmoProperty>>(() => new List<NodeSmoProperty>
|
||||
{
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "Computed",
|
||||
ValidFor = ValidForFlag.All
|
||||
},
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "IsColumnSet",
|
||||
ValidFor = ValidForFlag.All
|
||||
},
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "Nullable",
|
||||
ValidFor = ValidForFlag.All
|
||||
},
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "DataType",
|
||||
ValidFor = ValidForFlag.All
|
||||
},
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "InPrimaryKey",
|
||||
ValidFor = ValidForFlag.All
|
||||
},
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "IsForeignKey",
|
||||
ValidFor = ValidForFlag.All
|
||||
},
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "SystemType",
|
||||
ValidFor = ValidForFlag.All
|
||||
},
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "Length",
|
||||
ValidFor = ValidForFlag.All
|
||||
},
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "NumericPrecision",
|
||||
ValidFor = ValidForFlag.All
|
||||
},
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "NumericScale",
|
||||
ValidFor = ValidForFlag.All
|
||||
},
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "XmlSchemaNamespaceSchema",
|
||||
ValidFor = ValidForFlag.NotSqlDw
|
||||
},
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "XmlSchemaNamespace",
|
||||
ValidFor = ValidForFlag.NotSqlDw
|
||||
},
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "XmlDocumentConstraint",
|
||||
ValidFor = ValidForFlag.NotSqlDw
|
||||
}
|
||||
});
|
||||
|
||||
public override IEnumerable<NodeSmoProperty> SmoProperties => smoPropertiesLazy.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom name for UserDefinedTableTypeColumn
|
||||
/// </summary>
|
||||
internal partial class UserDefinedTableTypeColumnsChildFactory : DataSourceChildFactoryBase
|
||||
{
|
||||
public override string GetNodeCustomName(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return SmoColumnCustomNodeHelper.CalculateCustomLabel(objectMetadata, oeContext);
|
||||
}
|
||||
}
|
||||
|
||||
static class SmoColumnCustomNodeHelper
|
||||
{
|
||||
private const string SimpleColumnLabelWithType = "{0} ({1}{2}, {3})";
|
||||
private const string SimpleColumnLabelWithoutType = "{0} ({1})";
|
||||
private const string SimpleColumnLabelWithTypeAndKeyString = "{0} ({1}, {2}, {3})";
|
||||
|
||||
internal static string CalculateCustomLabel(object context, QueryContext oeContext)
|
||||
{
|
||||
UserDefinedDataTypeCollection uddts = null; // TODOKusto: Remove. Not needed.
|
||||
Column column = context as Column;
|
||||
if(column != null)
|
||||
{
|
||||
return GetCustomizedLabel(column, uddts);
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private static string GetCustomizedLabel(Column column, UserDefinedDataTypeCollection uddts)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (column.Computed)
|
||||
{
|
||||
return GetComputedColumnLabel(column, uddts);
|
||||
}
|
||||
else if (column.IsColumnSet)
|
||||
{
|
||||
return GetColumnSetLabel(column, uddts);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetSimpleColumnLabel(column, uddts);
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Logger.Write(TraceEventType.Error, $"Failed to get customized column name. error:{ex.Message}");
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private static string GetTypeSpecifierLabel(DataType dataType, UserDefinedDataTypeCollection uddts)
|
||||
{
|
||||
string typeName = string.Empty;
|
||||
if (dataType != null)
|
||||
{
|
||||
// typeSpecifier might still be in a resolve candidate status. If so then the
|
||||
// name might be null. Don't ask for the type specifier name in this case.
|
||||
typeName = dataType.Name;
|
||||
|
||||
// This may return [dbo].[MyType], but for the purposes of display we only want MyType
|
||||
if (!string.IsNullOrWhiteSpace(typeName) &&
|
||||
typeName.EndsWith("]", StringComparison.Ordinal))
|
||||
{
|
||||
int nameStart = typeName.LastIndexOf('[');
|
||||
typeName = typeName.Substring(nameStart + 1, typeName.Length - nameStart - 2);
|
||||
|
||||
}
|
||||
|
||||
if(dataType.SqlDataType == SqlDataType.UserDefinedDataType && uddts != null)
|
||||
{
|
||||
foreach (UserDefinedDataType item in uddts)
|
||||
{
|
||||
if(item.Name == dataType.Name)
|
||||
{
|
||||
typeName += $"({item.SystemType})";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These types supports detailed information
|
||||
switch (dataType.SqlDataType)
|
||||
{
|
||||
case SqlDataType.Char:
|
||||
case SqlDataType.NChar:
|
||||
case SqlDataType.Binary:
|
||||
case SqlDataType.VarChar:
|
||||
case SqlDataType.NVarChar:
|
||||
case SqlDataType.VarBinary:
|
||||
typeName += $"({dataType.MaximumLength})";
|
||||
break;
|
||||
case SqlDataType.Numeric:
|
||||
case SqlDataType.Decimal:
|
||||
typeName += $"({dataType.NumericPrecision},{dataType.NumericScale})";
|
||||
break;
|
||||
case SqlDataType.DateTime2:
|
||||
case SqlDataType.Time:
|
||||
case SqlDataType.DateTimeOffset:
|
||||
typeName += $"({dataType.NumericScale})";
|
||||
break;
|
||||
case SqlDataType.VarBinaryMax:
|
||||
case SqlDataType.NVarCharMax:
|
||||
case SqlDataType.VarCharMax:
|
||||
typeName += "(max)";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return typeName;
|
||||
}
|
||||
|
||||
private static string GetKeyString(Column column)
|
||||
{
|
||||
// Get if it's a PK or FK (or both)
|
||||
// Here's how it could be both...notice t2c1 is both a primary and foreign key
|
||||
//
|
||||
// Create table t1 (t1c1 int, t1c2 int not null primary key)
|
||||
// Create table t2 (t2c1 int primary key, t2c2 int not null)
|
||||
// Alter table t2 add FOREIGN KEY(t2c1) references t1(t1c2)
|
||||
//
|
||||
string keyString = null;
|
||||
if (column.InPrimaryKey)
|
||||
keyString = "PK";
|
||||
if (column.IsForeignKey)
|
||||
{
|
||||
keyString = (keyString == null) ? "FK" :
|
||||
"PK, FK";
|
||||
}
|
||||
|
||||
return keyString;
|
||||
}
|
||||
|
||||
private static string GetColumnSetLabel(Column column, UserDefinedDataTypeCollection uddts)
|
||||
{
|
||||
// This is the simple name
|
||||
string label = column.Name;
|
||||
|
||||
// Get the column type
|
||||
string columnType = GetTypeSpecifierLabel(column.DataType, uddts);
|
||||
string keyString = GetKeyString(column);
|
||||
|
||||
if (keyString != null && !string.IsNullOrWhiteSpace(columnType))
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture,
|
||||
SR.SchemaHierarchy_ColumnSetLabelWithTypeAndKeyString,
|
||||
label,
|
||||
keyString,
|
||||
columnType,
|
||||
SR.SchemaHierarchy_NullColumn_Label);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(columnType))
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture,
|
||||
SR.SchemaHierarchy_ColumnSetLabelWithType,
|
||||
label,
|
||||
keyString,
|
||||
columnType,
|
||||
SR.SchemaHierarchy_NullColumn_Label);
|
||||
}
|
||||
|
||||
return string.Format(CultureInfo.InvariantCulture,
|
||||
SR.SchemaHierarchy_ColumnSetLabelWithoutType,
|
||||
label,
|
||||
SR.SchemaHierarchy_NullColumn_Label);
|
||||
}
|
||||
|
||||
private static string GetSimpleColumnLabel(Column column, UserDefinedDataTypeCollection uddts)
|
||||
{
|
||||
// This is the simple name
|
||||
string label = column.Name;
|
||||
|
||||
// Get the nullability
|
||||
string isNullable = column.Nullable ? SR.SchemaHierarchy_NullColumn_Label : SR.SchemaHierarchy_NotNullColumn_Label;
|
||||
|
||||
// Get the column type
|
||||
string columnType = GetTypeSpecifierLabel(column.DataType, uddts);
|
||||
|
||||
string keyString = GetKeyString(column);
|
||||
|
||||
if (keyString != null && !string.IsNullOrWhiteSpace(columnType))
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture,
|
||||
SimpleColumnLabelWithTypeAndKeyString,
|
||||
label,
|
||||
keyString,
|
||||
columnType,
|
||||
isNullable);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(columnType))
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture,
|
||||
SimpleColumnLabelWithType,
|
||||
label,
|
||||
keyString,
|
||||
columnType,
|
||||
isNullable);
|
||||
}
|
||||
|
||||
return string.Format(CultureInfo.InvariantCulture,
|
||||
SimpleColumnLabelWithoutType,
|
||||
label,
|
||||
isNullable);
|
||||
}
|
||||
|
||||
private static string GetComputedColumnLabel(Column column, UserDefinedDataTypeCollection uddts)
|
||||
{
|
||||
string columnType = null;
|
||||
|
||||
// Display the type name as fully qualified
|
||||
string label = column.Name;
|
||||
|
||||
// Get the nullability
|
||||
string isNullable = column.Nullable ? SR.SchemaHierarchy_NullColumn_Label : SR.SchemaHierarchy_NotNullColumn_Label;
|
||||
|
||||
string keyString = GetKeyString(column);
|
||||
|
||||
// Get the column type
|
||||
columnType = GetTypeSpecifierLabel(column.DataType, uddts);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(columnType))
|
||||
{
|
||||
if (column.Parent is View)
|
||||
{
|
||||
// View columns are always computed, but SSMS shows then as never computed, so
|
||||
// treat them as simple columns
|
||||
return string.Format(CultureInfo.InvariantCulture,
|
||||
SimpleColumnLabelWithType,
|
||||
label,
|
||||
keyString,
|
||||
columnType,
|
||||
isNullable);
|
||||
}
|
||||
return string.Format(CultureInfo.InvariantCulture,
|
||||
SR.SchemaHierarchy_ComputedColumnLabelWithType,
|
||||
label,
|
||||
keyString,
|
||||
columnType,
|
||||
isNullable);
|
||||
}
|
||||
|
||||
if (column.Parent is View)
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture,
|
||||
SimpleColumnLabelWithoutType,
|
||||
label,
|
||||
keyString);
|
||||
}
|
||||
return string.Format(CultureInfo.InvariantCulture,
|
||||
SR.SchemaHierarchy_ComputedColumnLabelWithoutType,
|
||||
label,
|
||||
keyString);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
//
|
||||
// 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.Kusto.ServiceLayer.ObjectExplorer.Nodes;
|
||||
using Microsoft.Kusto.ServiceLayer.DataSource.Metadata;
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Status for databases
|
||||
/// </summary>
|
||||
internal partial class DatabasesChildFactory : DataSourceChildFactoryBase
|
||||
{
|
||||
public override string GetNodeStatus(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return DatabasesCustomNodeHelper.GetStatus(objectMetadata, oeContext, CachedSmoProperties);
|
||||
}
|
||||
|
||||
protected override void InitializeChild(TreeNode parent, TreeNode child, object context)
|
||||
{
|
||||
base.InitializeChild(parent, child, context);
|
||||
var dsTreeNode = child as DataSourceTreeNode;
|
||||
if (dsTreeNode != null && dsTreeNode.ObjectMetadata != null
|
||||
&& DatabasesCustomNodeHelper.GetDatabaseIsUnavailable(dsTreeNode.ObjectMetadata, parent.GetContextAs<QueryContext>(), CachedSmoProperties))
|
||||
{
|
||||
child.IsAlwaysLeaf = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class DatabasesCustomNodeHelper
|
||||
{
|
||||
private static readonly DatabaseStatus[] UnavailableDatabaseStatuses = { DatabaseStatus.Inaccessible, DatabaseStatus.Offline, DatabaseStatus.Recovering,
|
||||
DatabaseStatus.RecoveryPending, DatabaseStatus.Restoring, DatabaseStatus.Suspect, DatabaseStatus.Shutdown };
|
||||
|
||||
internal static bool GetDatabaseIsUnavailable(object objectMetadata, QueryContext oeContext, IEnumerable<NodeSmoProperty> supportedProperties)
|
||||
{
|
||||
if(oeContext.DataSource == null) return false; // Assume that database is available
|
||||
|
||||
return !oeContext.DataSource.Exists(objectMetadata as DataSourceObjectMetadata);
|
||||
}
|
||||
|
||||
internal static string GetStatus(object objectMetadata, QueryContext oeContext, IEnumerable<NodeSmoProperty> supportedProperties)
|
||||
{
|
||||
// TODOKusto: Remove if not needed. Returning a value appends it to the database name
|
||||
// if(oeContext.DataSource.Exists(objectMetadata as DataSourceObjectMetadata)) return "Online";
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
//
|
||||
// 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.Kusto.ServiceLayer.ObjectExplorer.Nodes;
|
||||
using Index = Microsoft.SqlServer.Management.Smo.Index;
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Subtye for keys
|
||||
/// </summary>
|
||||
internal partial class KeysChildFactory : DataSourceChildFactoryBase
|
||||
{
|
||||
public override string GetNodeSubType(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return IndexCustomeNodeHelper.GetSubType(objectMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sub types and custom name for indexes
|
||||
/// </summary>
|
||||
internal partial class IndexesChildFactory : DataSourceChildFactoryBase
|
||||
{
|
||||
private readonly Lazy<List<NodeSmoProperty>> smoPropertiesLazy = new Lazy<List<NodeSmoProperty>>(() => new List<NodeSmoProperty>
|
||||
{
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "IsUnique",
|
||||
ValidFor = ValidForFlag.All
|
||||
},
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "IsClustered",
|
||||
ValidFor = ValidForFlag.All
|
||||
},
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "IndexKeyType",
|
||||
ValidFor = ValidForFlag.All
|
||||
}
|
||||
});
|
||||
|
||||
public override IEnumerable<NodeSmoProperty> SmoProperties => smoPropertiesLazy.Value;
|
||||
|
||||
public override string GetNodeSubType(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return IndexCustomeNodeHelper.GetSubType(objectMetadata);
|
||||
}
|
||||
|
||||
public override string GetNodeCustomName(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return IndexCustomeNodeHelper.GetCustomLabel(objectMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// sub type for UserDefinedTableTypeKeys
|
||||
/// </summary>
|
||||
internal partial class UserDefinedTableTypeKeysChildFactory : DataSourceChildFactoryBase
|
||||
{
|
||||
public override string GetNodeSubType(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return IndexCustomeNodeHelper.GetSubType(objectMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class IndexCustomeNodeHelper
|
||||
{
|
||||
internal static string GetCustomLabel(object context)
|
||||
{
|
||||
Index index = context as Index;
|
||||
if (index != null)
|
||||
{
|
||||
string name = index.Name;
|
||||
string unique = index.IsUnique ? SR.UniqueIndex_LabelPart : SR.NonUniqueIndex_LabelPart;
|
||||
string clustered = index.IsClustered ? SR.ClusteredIndex_LabelPart : SR.NonClusteredIndex_LabelPart;
|
||||
name = name + $" ({unique}, {clustered})";
|
||||
return name;
|
||||
}
|
||||
return string.Empty;
|
||||
|
||||
}
|
||||
|
||||
internal static string GetSubType(object context)
|
||||
{
|
||||
|
||||
Index index = context as Index;
|
||||
if (index != null)
|
||||
{
|
||||
switch (index.IndexKeyType)
|
||||
{
|
||||
case IndexKeyType.DriPrimaryKey:
|
||||
return "PrimaryKey";
|
||||
case IndexKeyType.DriUniqueKey:
|
||||
return "UniqueKey";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ForeignKey foreignKey = context as ForeignKey;
|
||||
if (foreignKey != null)
|
||||
{
|
||||
return "ForeignKey";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
//
|
||||
// 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.Kusto.ServiceLayer.ObjectExplorer.Nodes;
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Status for logins
|
||||
/// </summary>
|
||||
internal partial class ServerLevelLoginsChildFactory : DataSourceChildFactoryBase
|
||||
{
|
||||
public override string GetNodeStatus(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return LoginCustomNodeHelper.GetStatus(objectMetadata);
|
||||
}
|
||||
|
||||
private readonly Lazy<List<NodeSmoProperty>> smoPropertiesLazy = new Lazy<List<NodeSmoProperty>>(() => new List<NodeSmoProperty>
|
||||
{
|
||||
new NodeSmoProperty
|
||||
{
|
||||
Name = "IsDisabled",
|
||||
ValidFor = ValidForFlag.All
|
||||
}
|
||||
});
|
||||
|
||||
public override IEnumerable<NodeSmoProperty> SmoProperties => smoPropertiesLazy.Value;
|
||||
}
|
||||
|
||||
internal static class LoginCustomNodeHelper
|
||||
{
|
||||
internal static string GetStatus(object context)
|
||||
{
|
||||
Login login = context as Login;
|
||||
if (login != null)
|
||||
{
|
||||
if (login.IsDisabled)
|
||||
{
|
||||
return "Disabled";
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.Globalization;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Custom name for parameters
|
||||
/// </summary>
|
||||
internal partial class TableValuedFunctionParametersChildFactory : DataSourceChildFactoryBase
|
||||
{
|
||||
public override string GetNodeCustomName(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return ParameterCustomeNodeHelper.GetCustomLabel(objectMetadata, oeContext);
|
||||
}
|
||||
|
||||
public override string GetNodeSubType(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return ParameterCustomeNodeHelper.GetSubType(objectMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom name for parameters
|
||||
/// </summary>
|
||||
internal partial class ScalarValuedFunctionParametersChildFactory : DataSourceChildFactoryBase
|
||||
{
|
||||
public override string GetNodeCustomName(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return ParameterCustomeNodeHelper.GetCustomLabel(objectMetadata, oeContext);
|
||||
}
|
||||
public override string GetNodeSubType(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return ParameterCustomeNodeHelper.GetSubType(objectMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom name for parameters
|
||||
/// </summary>
|
||||
internal partial class AggregateFunctionParametersChildFactory : DataSourceChildFactoryBase
|
||||
{
|
||||
public override string GetNodeCustomName(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return ParameterCustomeNodeHelper.GetCustomLabel(objectMetadata, oeContext);
|
||||
}
|
||||
public override string GetNodeSubType(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return ParameterCustomeNodeHelper.GetSubType(objectMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom name for parameters
|
||||
/// </summary>
|
||||
internal partial class StoredProcedureParametersChildFactory : DataSourceChildFactoryBase
|
||||
{
|
||||
public override string GetNodeCustomName(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return ParameterCustomeNodeHelper.GetCustomLabel(objectMetadata, oeContext);
|
||||
}
|
||||
public override string GetNodeSubType(object objectMetadata, QueryContext oeContext)
|
||||
{
|
||||
return ParameterCustomeNodeHelper.GetSubType(objectMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
static class ParameterCustomeNodeHelper
|
||||
{
|
||||
internal static string GetSubType(object context)
|
||||
{
|
||||
Parameter parameter = context as Parameter;
|
||||
if (parameter != null)
|
||||
{
|
||||
StoredProcedureParameter stordProcedureParameter = parameter as StoredProcedureParameter;
|
||||
if (stordProcedureParameter != null && stordProcedureParameter.IsOutputParameter)
|
||||
{
|
||||
return "Output";
|
||||
}
|
||||
return "Input";
|
||||
//TODO return parameters
|
||||
}
|
||||
return string.Empty;
|
||||
|
||||
}
|
||||
|
||||
internal static string GetCustomLabel(object context, QueryContext oeContext)
|
||||
{
|
||||
Parameter parameter = context as Parameter;
|
||||
if (parameter != null)
|
||||
{
|
||||
return GetParameterCustomLabel(parameter);
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
internal static string GetParameterCustomLabel(Parameter parameter)
|
||||
{
|
||||
string label = parameter.Name;
|
||||
string defaultString = SR.SchemaHierarchy_SubroutineParameterNoDefaultLabel;
|
||||
string inputOutputString = SR.SchemaHierarchy_SubroutineParameterInputLabel;
|
||||
string typeName = parameter.DataType.ToString();
|
||||
|
||||
if (parameter.DefaultValue != null &&
|
||||
!string.IsNullOrEmpty(parameter.DefaultValue))
|
||||
{
|
||||
defaultString = SR.SchemaHierarchy_SubroutineParameterDefaultLabel;
|
||||
}
|
||||
|
||||
StoredProcedureParameter stordProcedureParameter = parameter as StoredProcedureParameter;
|
||||
if (stordProcedureParameter != null && stordProcedureParameter.IsOutputParameter)
|
||||
{
|
||||
inputOutputString = SR.SchemaHierarchy_SubroutineParameterInputOutputLabel;
|
||||
if (parameter.IsReadOnly)
|
||||
{
|
||||
inputOutputString = SR.SchemaHierarchy_SubroutineParameterInputOutputReadOnlyLabel;
|
||||
}
|
||||
}
|
||||
else if (parameter.IsReadOnly)
|
||||
{
|
||||
inputOutputString = SR.SchemaHierarchy_SubroutineParameterInputReadOnlyLabel;
|
||||
}
|
||||
|
||||
return string.Format(CultureInfo.InvariantCulture,
|
||||
SR.SchemaHierarchy_SubroutineParameterLabelFormatString,
|
||||
label,
|
||||
typeName,
|
||||
inputOutputString,
|
||||
defaultString);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
//
|
||||
// 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 System.Data;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.Extensibility;
|
||||
using Microsoft.Kusto.ServiceLayer.DataSource.Metadata;
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="DataSourceQuerier"/> 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 DataSourceQuerier : IComposableService
|
||||
{
|
||||
private static object lockObject = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Queries SMO for a collection of objects using the <see cref="QueryContext"/>
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public abstract IEnumerable<DataSourceObjectMetadata> Query(QueryContext context, string filter, bool refresh, IEnumerable<string> extraProperties);
|
||||
|
||||
internal IMultiServiceProvider ServiceProvider
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public void SetServiceProvider(IMultiServiceProvider provider)
|
||||
{
|
||||
ServiceProvider = provider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the data to data reader is possible
|
||||
/// </summary>
|
||||
protected IDataReader GetDataReader(object data)
|
||||
{
|
||||
IDataReader reader = null;
|
||||
if (data is IDataReader)
|
||||
{
|
||||
|
||||
reader = data as IDataReader;
|
||||
}
|
||||
else if(data is DataTable)
|
||||
{
|
||||
reader = ((DataTable)data).CreateDataReader();
|
||||
}
|
||||
|
||||
else if (data is DataSet)
|
||||
{
|
||||
reader = ((DataSet)data).Tables[0].CreateDataReader();
|
||||
}
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mthod used to do custom filtering on smo objects if cannot be implemented using the filters
|
||||
/// </summary>
|
||||
protected virtual bool PassesFinalFilters(SqlSmoObject parent, SqlSmoObject objectMetadata)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates which platforms the querier is valid for
|
||||
/// </summary>
|
||||
public virtual ValidForFlag ValidFor
|
||||
{
|
||||
get
|
||||
{
|
||||
return ValidForFlag.All;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,320 +0,0 @@
|
||||
<#@ 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.Kusto.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);
|
||||
var validFor = nodeElement.GetAttribute("ValidFor");
|
||||
|
||||
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 + ") };");
|
||||
if (!string.IsNullOrWhiteSpace(validFor))
|
||||
{
|
||||
WriteLine("");
|
||||
WriteLine(string.Format("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);
|
||||
|
||||
// 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);
|
||||
|
||||
XmlElement navPathElement = GetNavPathElement(xmlFile, nodeName, parentType);
|
||||
string navigationPath = GetNavigationPath(nodeElement, nodeName, navPathElement);
|
||||
string subField = GetNavPathAttribute(navPathElement, "SubField");
|
||||
string fieldType = GetNavPathAttribute(navPathElement, "FieldType");
|
||||
|
||||
|
||||
WriteLine(string.Format("var retValue = {0}.{1};", parentVar, navigationPath));
|
||||
WriteLine("if (retValue != null)");
|
||||
WriteLine("{");
|
||||
PushIndent(indent);
|
||||
|
||||
|
||||
if (IsCollection(nodeElement))
|
||||
{
|
||||
WriteLine(string.Format("retValue.ClearAndInitialize(filter, extraProperties);"));
|
||||
if (string.IsNullOrEmpty(subField) )
|
||||
{
|
||||
WriteLine(string.Format("return new SmoCollectionWrapper<{0}>(retValue).Where(c => PassesFinalFilters({1}, c));", nodeType, parentVar));
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine(string.Format("List<{0}> subFieldResult = new List<{0}>();", nodeType));
|
||||
WriteLine(string.Format("foreach({0} field in retValue)", fieldType));
|
||||
WriteLine("{");
|
||||
PushIndent(indent);
|
||||
WriteLine(string.Format("{0} subField = field.{1};", nodeType, subField));
|
||||
WriteLine(string.Format("if (subField != null)"));
|
||||
WriteLine("{");
|
||||
PushIndent(indent);
|
||||
WriteLine(string.Format("subFieldResult.Add(subField);"));
|
||||
PopIndent();
|
||||
WriteLine("}");
|
||||
PopIndent();
|
||||
WriteLine("}");
|
||||
WriteLine(string.Format("return subFieldResult.Where(c => PassesFinalFilters({1}, c));", nodeType, parentVar));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine("if (refresh)");
|
||||
WriteLine("{");
|
||||
PushIndent(indent);
|
||||
WriteLine(string.Format("{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();
|
||||
}
|
||||
#>
|
||||
}
|
||||
|
||||
<#+
|
||||
|
||||
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 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))
|
||||
{
|
||||
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>();
|
||||
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;
|
||||
}
|
||||
|
||||
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("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 == "All")
|
||||
{
|
||||
flags.Add("ValidForFlag.All");
|
||||
}
|
||||
|
||||
return string.Join("|", flags);
|
||||
}
|
||||
|
||||
#>
|
||||
@@ -1,164 +0,0 @@
|
||||
<?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" ValidFor="NotSqlDw" >
|
||||
<NavigationPath Parent="Server" Field="Triggers" />
|
||||
</Node>
|
||||
|
||||
<Node Name="SqlErrorMessage" Type="UserDefinedMessage" Parent="Server" />
|
||||
|
||||
<Node Name="SqlTable" Parent="Database" />
|
||||
<Node Name="SqlHistoryTable" Type="Table" Parent="Table" >
|
||||
<NavigationPath Parent="Table" Type="Table" Field="Parent.Tables" />
|
||||
</Node>
|
||||
|
||||
<Node Name="SqlView" Parent="Database" />
|
||||
|
||||
<Node Name="SqlSynonym" Parent="Database" ValidFor="NotSqlDw" />
|
||||
|
||||
<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" Collection="True" >
|
||||
<Parent>Table</Parent>
|
||||
<Parent>UserDefinedTableType</Parent>
|
||||
<NavigationPath Parent="Table" Field="Columns" SubField="DefaultConstraint" FieldType="Column" />
|
||||
<NavigationPath Parent="UserDefinedTableType" Field="Columns" SubField="DefaultConstraint" FieldType="Column" />
|
||||
</Node>
|
||||
<Node Name="SqlDmlTrigger" Type="Trigger" ValidFor="NotSqlDw">
|
||||
<Parent>Table</Parent>
|
||||
<Parent>View</Parent>
|
||||
</Node>
|
||||
<Node Name="SqlFullTextIndex" Parent="Table" Collection="False" ValidFor="NotSqlDw" />
|
||||
<Node Name="SqlStatistic" Parent="TableViewBase"/>
|
||||
|
||||
<Node Name="SqlDatabaseDdlTrigger" Type="DatabaseDdlTrigger" Parent="Database" ValidFor="NotSqlDw">
|
||||
<NavigationPath Parent="Database" Field="Triggers" />
|
||||
</Node>
|
||||
<Node Name="SqlAssembly" Type="SqlAssembly" Parent="Database" >
|
||||
<NavigationPath Parent="Database" Field="Assemblies" />
|
||||
</Node>
|
||||
|
||||
<!-- Deprecated
|
||||
<Node Name="SqlRule" Parent="Database" />
|
||||
<Node Name="SqlDefault" Parent="Database" />
|
||||
-->
|
||||
<Node Name="SqlSequence" Parent="Database" />
|
||||
|
||||
<Node Name="SqlUserDefinedDataType" Parent="Database" ValidFor="NotSqlDw" />
|
||||
|
||||
<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="Database">
|
||||
<NavigationPath Parent="Database" Field="Parent.SystemDataTypes" FieldForUrn="Parent" />
|
||||
</Node>
|
||||
<!-- 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>
|
||||
@@ -1,34 +0,0 @@
|
||||
//
|
||||
// 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;
|
||||
|
||||
|
||||
// TODOKusto: Remove this file. These classes might not be needed.
|
||||
namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Custom name for table
|
||||
/// </summary>
|
||||
internal partial class TablesChildFactory : DataSourceChildFactoryBase
|
||||
{
|
||||
// TODOKusto: If we are always passing DataSourceMetadataObject, stop passing object. Make it type safe.
|
||||
public override string GetNodePathName(object objectMetadata)
|
||||
{
|
||||
return base.GetNodePathName(objectMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom name for history table
|
||||
/// </summary>
|
||||
internal partial class TableChildFactory : DataSourceChildFactoryBase
|
||||
{
|
||||
public override string GetNodePathName(object objectMetadata)
|
||||
{
|
||||
return base.GetNodePathName(objectMetadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,11 +24,6 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer.DataSourceModel
|
||||
{
|
||||
}
|
||||
|
||||
/// <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
|
||||
|
||||
@@ -1,564 +0,0 @@
|
||||
<#@ 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.SqlServer.Management.Smo;
|
||||
using Microsoft.Kusto.ServiceLayer;
|
||||
using Microsoft.Kusto.ServiceLayer.ObjectExplorer.Nodes;
|
||||
|
||||
namespace Microsoft.Kusto.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} : OETreeNode", 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 nodeType = nodeElement.GetAttribute("NodeType");
|
||||
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);
|
||||
List<XmlElement> filters = GetNodeFilters(xmlFile, type);
|
||||
List<XmlElement> smoProperties = GetNodeSmoProperties(xmlFile, type);
|
||||
|
||||
if (filters.Count > 0)
|
||||
{
|
||||
WriteLine("");
|
||||
WriteLine(" public override IEnumerable<NodeFilter> Filters");
|
||||
WriteLine(" {");
|
||||
WriteLine(" get");
|
||||
WriteLine(" {");
|
||||
|
||||
WriteLine(" var filters = new List<NodeFilter>();");
|
||||
foreach (var filter in filters)
|
||||
{
|
||||
var propertyName = filter.GetAttribute("Property");
|
||||
var propertyType = filter.GetAttribute("Type");
|
||||
var propertyValue = filter.GetAttribute("Value");
|
||||
var validFor = filter.GetAttribute("ValidFor");
|
||||
var typeToReverse = filter.GetAttribute("TypeToReverse");
|
||||
|
||||
List<XmlElement> filterValues = GetNodeFilterValues(xmlFile, type, propertyName);
|
||||
|
||||
|
||||
WriteLine(" filters.Add(new NodeFilter");
|
||||
WriteLine(" {");
|
||||
WriteLine(string.Format(" Property = \"{0}\",", propertyName));
|
||||
WriteLine(string.Format(" Type = typeof({0}),", propertyType));
|
||||
if (!string.IsNullOrWhiteSpace(typeToReverse))
|
||||
{
|
||||
WriteLine(string.Format(" TypeToReverse = typeof({0}Querier),", typeToReverse));
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(validFor))
|
||||
{
|
||||
WriteLine(string.Format(" ValidFor = {0},", GetValidForFlags(validFor)));
|
||||
}
|
||||
if (propertyValue != null && (filterValues == null || filterValues.Count == 0))
|
||||
{
|
||||
WriteLine(string.Format(" Values = new List<object> {{ {0} }},", propertyValue));
|
||||
}
|
||||
if (filterValues != null && filterValues.Count > 0)
|
||||
{
|
||||
string filterValueType = "object";
|
||||
if (propertyType == "Enum")
|
||||
{
|
||||
|
||||
}
|
||||
WriteLine(string.Format(" Values = new List<object>"));
|
||||
WriteLine(string.Format(" {{"));
|
||||
for(int i = 0; i < filterValues.Count; i++)
|
||||
{
|
||||
string separator = "";
|
||||
if (i != filterValues.Count - 1)
|
||||
{
|
||||
separator = ",";
|
||||
}
|
||||
var filterValue = filterValues[i];
|
||||
WriteLine(string.Format(" {{ {0} }}{1}", filterValue.InnerText, separator ));
|
||||
|
||||
}
|
||||
WriteLine(string.Format(" }}"));
|
||||
}
|
||||
WriteLine(" });");
|
||||
|
||||
|
||||
}
|
||||
|
||||
WriteLine(" return filters;");
|
||||
WriteLine(" }");
|
||||
WriteLine(" }");
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (smoProperties.Count > 0)
|
||||
{
|
||||
WriteLine("");
|
||||
WriteLine(" public override IEnumerable<NodeSmoProperty> SmoProperties");
|
||||
WriteLine(" {");
|
||||
WriteLine(" get");
|
||||
WriteLine(" {");
|
||||
|
||||
WriteLine(" var properties = new List<NodeSmoProperty>();");
|
||||
foreach (var smoPropertiy in smoProperties)
|
||||
{
|
||||
var propertyName = smoPropertiy.GetAttribute("Name");
|
||||
var validFor = smoPropertiy.GetAttribute("ValidFor");
|
||||
|
||||
|
||||
|
||||
|
||||
WriteLine(" properties.Add(new NodeSmoProperty");
|
||||
WriteLine(" {");
|
||||
WriteLine(string.Format(" Name = \"{0}\",", propertyName));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(validFor))
|
||||
{
|
||||
WriteLine(string.Format(" ValidFor = {0}", GetValidForFlags(validFor)));
|
||||
}
|
||||
WriteLine(" });");
|
||||
|
||||
|
||||
}
|
||||
|
||||
WriteLine(" return properties;");
|
||||
WriteLine(" }");
|
||||
WriteLine(" }");
|
||||
|
||||
}
|
||||
|
||||
|
||||
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 = OETreeNode.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")));
|
||||
WriteLine(string.Format(" IsSystemObject = {0},", child.GetAttribute("IsSystemObject") == "1" ? "true" : "false"));
|
||||
|
||||
if (msShippedOwned != null)
|
||||
{
|
||||
WriteLine(" IsMsShippedOwned = true,");
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(validFor))
|
||||
{
|
||||
WriteLine(string.Format(" ValidFor = {0},", GetValidForFlags(validFor)));
|
||||
}
|
||||
WriteLine(" SortPriority = OETreeNode.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 OETreeNode();");
|
||||
WriteLine(" child.IsAlwaysLeaf = true;");
|
||||
|
||||
if (!string.IsNullOrEmpty(nodeType))
|
||||
{
|
||||
|
||||
WriteLine(string.Format(" child.NodeType = \"{0}\";", nodeType));
|
||||
}
|
||||
|
||||
}
|
||||
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 = OETreeNode.NextSortPriority;");
|
||||
}
|
||||
WriteLine(" InitializeChild(parent, 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("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 == "All")
|
||||
{
|
||||
flags.Add("ValidForFlag.All");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public static List<XmlElement> GetNodeFilters(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}']/Filters/Filter", parentName));
|
||||
foreach (var item in nodeList)
|
||||
{
|
||||
XmlElement itemAsElement = item as XmlElement;
|
||||
if (itemAsElement != null)
|
||||
{
|
||||
retElements.Add(itemAsElement);
|
||||
}
|
||||
}
|
||||
return retElements;
|
||||
}
|
||||
|
||||
|
||||
public static List<XmlElement> GetNodeSmoProperties(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}']/Properties/Property", parentName));
|
||||
foreach (var item in nodeList)
|
||||
{
|
||||
XmlElement itemAsElement = item as XmlElement;
|
||||
if (itemAsElement != null)
|
||||
{
|
||||
retElements.Add(itemAsElement);
|
||||
}
|
||||
}
|
||||
return retElements;
|
||||
}
|
||||
|
||||
public static List<XmlElement> GetNodeFilterValues(string xmlFile, string parentName, string filterProperty)
|
||||
{
|
||||
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}']/Filters/Filter[@Property='{1}']/Value", parentName, filterProperty));
|
||||
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