mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-17 17:23:48 -05:00
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.SqlTools.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"></param>
|
||||
/// <returns></returns>
|
||||
public abstract IEnumerable<TreeNode> Expand(TreeNode parent);
|
||||
|
||||
public abstract bool CanCreateChild(TreeNode parent, object context);
|
||||
public abstract TreeNode CreateChild(TreeNode parent, object context);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
//
|
||||
// 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.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection class for <see cref="TreeNode"/>
|
||||
/// </summary>
|
||||
public sealed class NodeObservableCollection : ObservableCollection<TreeNode>
|
||||
{
|
||||
public event EventHandler Initialized;
|
||||
private int? numInits;
|
||||
private static int cleanupBlocker;
|
||||
|
||||
public bool IsInitialized
|
||||
{
|
||||
get { return numInits.HasValue && numInits == 0; }
|
||||
}
|
||||
|
||||
public bool IsPopulating
|
||||
{
|
||||
get { return numInits.HasValue && numInits != 0; }
|
||||
}
|
||||
|
||||
public void BeginInit()
|
||||
{
|
||||
if (!numInits.HasValue)
|
||||
{
|
||||
numInits = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
numInits = numInits + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public void EndInit()
|
||||
{
|
||||
IList<TreeNode> empty = null;
|
||||
EndInit(null, ref empty);
|
||||
}
|
||||
|
||||
public void EndInit(TreeNode parent, ref IList<TreeNode> deferredChildren)
|
||||
{
|
||||
if (numInits.HasValue &&
|
||||
numInits.Value == 1)
|
||||
{
|
||||
try
|
||||
{
|
||||
DoSort();
|
||||
|
||||
if (deferredChildren != null)
|
||||
{
|
||||
// Set the parents so the children know how to sort themselves
|
||||
foreach (var item in deferredChildren)
|
||||
{
|
||||
item.Parent = parent;
|
||||
}
|
||||
|
||||
deferredChildren = deferredChildren.OrderBy(x => x).ToList();
|
||||
|
||||
// Add the deferredChildren
|
||||
foreach (var item in deferredChildren)
|
||||
{
|
||||
this.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (deferredChildren != null)
|
||||
{
|
||||
deferredChildren.Clear();
|
||||
}
|
||||
numInits = numInits - 1;
|
||||
}
|
||||
|
||||
Initialized?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
numInits = numInits - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Repositions this child in the list
|
||||
/// </summary>
|
||||
public void ReSortChild(TreeNode child)
|
||||
{
|
||||
if (child == null)
|
||||
return;
|
||||
|
||||
List<TreeNode> sorted = this.OrderBy(x => x).ToList();
|
||||
|
||||
// Remove without cleanup
|
||||
try
|
||||
{
|
||||
cleanupBlocker++;
|
||||
Remove(child);
|
||||
}
|
||||
finally
|
||||
{
|
||||
cleanupBlocker--;
|
||||
}
|
||||
|
||||
// Then insert
|
||||
for (int i = 0; i < sorted.Count; i++)
|
||||
{
|
||||
if (sorted[i] == child)
|
||||
{
|
||||
Insert(i, child);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RemoveItem(int index)
|
||||
{
|
||||
// Cleanup all the children
|
||||
Cleanup(this[index]);
|
||||
|
||||
base.RemoveItem(index);
|
||||
}
|
||||
|
||||
protected override void ClearItems()
|
||||
{
|
||||
// Cleanup all the children
|
||||
foreach (var child in this)
|
||||
{
|
||||
Cleanup(child);
|
||||
}
|
||||
|
||||
base.ClearItems();
|
||||
}
|
||||
|
||||
private static void Cleanup(TreeNode parent)
|
||||
{
|
||||
if (cleanupBlocker > 0 ||
|
||||
parent.Parent == null)
|
||||
return;
|
||||
|
||||
// TODO implement cleanup policy / pattern
|
||||
//ICleanupPattern parentAsCleanup = parent as ICleanupPattern;
|
||||
//if (parentAsCleanup != null)
|
||||
// parentAsCleanup.DoCleanup();
|
||||
|
||||
//foreach (var child in parent.Children)
|
||||
//{
|
||||
// Cleanup(child);
|
||||
//}
|
||||
|
||||
parent.Parent = null;
|
||||
}
|
||||
|
||||
private void DoSort()
|
||||
{
|
||||
List<TreeNode> sorted = this.OrderBy(x => x).ToList();
|
||||
for (int i = 0; i < sorted.Count(); i++)
|
||||
{
|
||||
int index = IndexOf(sorted[i]);
|
||||
if (index != i)
|
||||
{
|
||||
Move(IndexOf(sorted[i]), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum listing possible node types in the object explorer tree
|
||||
/// </summary>
|
||||
// TODO Consider replacing this with an auto-gen'd version
|
||||
public enum NodeTypes
|
||||
{
|
||||
None,
|
||||
SqlServersRoot,
|
||||
DatabaseInstance,
|
||||
DacInstance,
|
||||
ServerInstance,
|
||||
ScalarValuedFunctionInstance,
|
||||
TableValuedFunctionInstance,
|
||||
AggregateFunctionInstance,
|
||||
FileGroupInstance,
|
||||
StoredProcedureInstance,
|
||||
UserDefinedTableTypeInstance,
|
||||
ViewInstance,
|
||||
TableInstance,
|
||||
HistoryTableInstance,
|
||||
Databases,
|
||||
ExternalResources,
|
||||
ServerLevelSecurity,
|
||||
ServerLevelServerObjects,
|
||||
ServerLevelManagement,
|
||||
SystemDatabases,
|
||||
ServerLevelLinkedServerLogins,
|
||||
ServerLevelServerAudits,
|
||||
ServerLevelCryptographicProviders,
|
||||
ServerLevelCredentials,
|
||||
ServerLevelServerRoles,
|
||||
ServerLevelLogins,
|
||||
ServerLevelEventSessions,
|
||||
ServerLevelServerAuditSpecifications,
|
||||
ServerLevelEventNotifications,
|
||||
ServerLevelErrorMessages,
|
||||
ServerLevelServerTriggers,
|
||||
ServerLevelLinkedServers,
|
||||
ServerLevelEndpoints,
|
||||
DacInstancesFolder,
|
||||
Tables,
|
||||
Views,
|
||||
Synonyms,
|
||||
Programmability,
|
||||
ServiceBroker,
|
||||
Storage,
|
||||
Security,
|
||||
SystemTables,
|
||||
FileTables,
|
||||
SystemViews,
|
||||
StoredProcedures,
|
||||
Functions,
|
||||
ExtendedStoredProcedures,
|
||||
DatabaseTriggers,
|
||||
Defaults,
|
||||
Rules,
|
||||
Types,
|
||||
Assemblies,
|
||||
MessageTypes,
|
||||
Contracts,
|
||||
Queues,
|
||||
Services,
|
||||
Routes,
|
||||
DatabaseAndQueueEventNotifications,
|
||||
RemoteServiceBindings,
|
||||
BrokerPriorities,
|
||||
FileGroups,
|
||||
FullTextCatalogs,
|
||||
FullTextStopLists,
|
||||
SqlLogFiles,
|
||||
PartitionFunctions,
|
||||
PartitionSchemes,
|
||||
SearchPropertyLists,
|
||||
Users,
|
||||
Roles,
|
||||
Schemas,
|
||||
AsymmetricKeys,
|
||||
Certificates,
|
||||
SymmetricKeys,
|
||||
DatabaseEncryptionKeys,
|
||||
MasterKeys,
|
||||
Signatures,
|
||||
DatabaseAuditSpecifications,
|
||||
Columns,
|
||||
Keys,
|
||||
Constraints,
|
||||
Triggers,
|
||||
Indexes,
|
||||
Statistics,
|
||||
TableValuedFunctions,
|
||||
ScalarValuedFunctions,
|
||||
AggregateFunctions,
|
||||
SystemDataTypes,
|
||||
UserDefinedDataTypes,
|
||||
UserDefinedTableTypes,
|
||||
UserDefinedTypes,
|
||||
XmlSchemaCollections,
|
||||
SystemExactNumerics,
|
||||
SystemApproximateNumerics,
|
||||
SystemDateAndTimes,
|
||||
SystemCharacterStrings,
|
||||
SystemUnicodeCharacterStrings,
|
||||
SystemBinaryStrings,
|
||||
SystemOtherDataTypes,
|
||||
SystemClrDataTypes,
|
||||
SystemSpatialDataTypes,
|
||||
UserDefinedTableTypeColumns,
|
||||
UserDefinedTableTypeKeys,
|
||||
UserDefinedTableTypeConstraints,
|
||||
SystemStoredProcedures,
|
||||
StoredProcedureParameters,
|
||||
TableValuedFunctionParameters,
|
||||
ScalarValuedFunctionParameters,
|
||||
AggregateFunctionParameters,
|
||||
DatabaseRoles,
|
||||
ApplicationRoles,
|
||||
FileGroupFiles,
|
||||
SystemMessageTypes,
|
||||
SystemContracts,
|
||||
SystemServices,
|
||||
SystemQueues,
|
||||
Sequences,
|
||||
SecurityPolicies,
|
||||
DatabaseScopedCredentials,
|
||||
ExternalTables,
|
||||
ExternalResourceInstance,
|
||||
ExternalDataSources,
|
||||
ExternalFileFormats,
|
||||
ExternalTableInstance,
|
||||
AlwaysEncryptedKeys,
|
||||
ColumnMasterKeys,
|
||||
ColumnEncryptionKeys
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
//
|
||||
// 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.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for elements in the object explorer tree. Provides common methods for tree navigation
|
||||
/// and other core functionality
|
||||
/// </summary>
|
||||
public class TreeNode : IComparable<TreeNode>
|
||||
{
|
||||
private NodeObservableCollection children = new NodeObservableCollection();
|
||||
private TreeNode parent;
|
||||
private string nodePath;
|
||||
private string label;
|
||||
private ObjectExplorerService objectExplorerService;
|
||||
public const char PathPartSeperator = '/';
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with no required inputs
|
||||
/// </summary>
|
||||
public TreeNode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that accepts a label to identify the node
|
||||
/// </summary>
|
||||
/// <param name="value">Label identifying the node</param>
|
||||
public TreeNode(string value)
|
||||
{
|
||||
// We intentionally do not valid this being null or empty since
|
||||
// some nodes may need to set it
|
||||
NodeValue = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Value describing this node
|
||||
/// </summary>
|
||||
public string NodeValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of the node - for example Server, Database, Folder, Table
|
||||
/// </summary>
|
||||
public string NodeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enum defining the type of the node - for example Server, Database, Folder, Table
|
||||
/// </summary>
|
||||
public NodeTypes NodeTypeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Label to display to the user, describing this node.
|
||||
/// If not explicitly set this will fall back to the <see cref="NodeValue"/> but
|
||||
/// for many nodes such as the server, the display label will be different
|
||||
/// to the value.
|
||||
/// </summary>
|
||||
public string Label {
|
||||
get
|
||||
{
|
||||
if(label == null)
|
||||
{
|
||||
return NodeValue;
|
||||
}
|
||||
return label;
|
||||
}
|
||||
set
|
||||
{
|
||||
label = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is this a leaf node (in which case no children can be generated) or
|
||||
/// is it expandable?
|
||||
/// </summary>
|
||||
public bool IsAlwaysLeaf { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Message to show if this Node is in an error state. This indicates
|
||||
/// that children could be retrieved
|
||||
/// </summary>
|
||||
public string ErrorStateMessage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parent of this node
|
||||
/// </summary>
|
||||
public TreeNode Parent
|
||||
{
|
||||
get
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
set
|
||||
{
|
||||
parent = value;
|
||||
// Reset the node path since it's no longer valid
|
||||
nodePath = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Path identifying this node: for example a table will be at ["server", "database", "tables", "tableName"].
|
||||
/// This enables rapid navigation of the tree without the need for a global registry of elements.
|
||||
/// The path functions as a unique ID and is used to disambiguate the node when sending requests for expansion.
|
||||
/// A common ID is needed since processes do not share address space and need a unique identifier
|
||||
/// </summary>
|
||||
public string GetNodePath()
|
||||
{
|
||||
if (nodePath == null)
|
||||
{
|
||||
GenerateNodePath();
|
||||
}
|
||||
return nodePath;
|
||||
}
|
||||
|
||||
private void GenerateNodePath()
|
||||
{
|
||||
string path = "";
|
||||
ObjectExplorerUtils.VisitChildAndParents(this, node =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(node.NodeValue))
|
||||
{
|
||||
// Hit a node with no NodeValue. This indicates we need to stop traversing
|
||||
return false;
|
||||
}
|
||||
// Otherwise add this value to the beginning of the path and keep iterating up
|
||||
path = string.Format(CultureInfo.InvariantCulture,
|
||||
"{0}{1}{2}", node.NodeValue, string.IsNullOrEmpty(path) ? "" : PathPartSeperator.ToString(), path);
|
||||
return true;
|
||||
});
|
||||
nodePath = path;
|
||||
}
|
||||
|
||||
public TreeNode FindNodeByPath(string path)
|
||||
{
|
||||
TreeNode nodeForPath = ObjectExplorerUtils.FindNode(this, node =>
|
||||
{
|
||||
return node.GetNodePath() == path;
|
||||
}, nodeToFilter =>
|
||||
{
|
||||
return path.StartsWith(nodeToFilter.GetNodePath());
|
||||
});
|
||||
|
||||
return nodeForPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a <see cref="NodeInfo"/> object for serialization with just the relevant properties
|
||||
/// needed to identify the node
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public NodeInfo ToNodeInfo()
|
||||
{
|
||||
return new NodeInfo()
|
||||
{
|
||||
IsLeaf = this.IsAlwaysLeaf,
|
||||
Label = this.Label,
|
||||
NodePath = this.GetNodePath(),
|
||||
NodeType = this.NodeType
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expands this node and returns its children
|
||||
/// </summary>
|
||||
/// <returns>Children as an IList. This is the raw children collection, not a copy</returns>
|
||||
public IList<TreeNode> Expand()
|
||||
{
|
||||
// TODO consider why solution explorer has separate Children and Items options
|
||||
if (children.IsInitialized)
|
||||
{
|
||||
return children;
|
||||
}
|
||||
PopulateChildren();
|
||||
return children;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a readonly view of the currently defined children for this node.
|
||||
/// This does not expand the node at all
|
||||
/// Since the tree needs to keep track of parent relationships, directly
|
||||
/// adding to the list is not supported.
|
||||
/// </summary>
|
||||
/// <returns><see cref="IList{TreeNode}"/> containing all children for this node</returns>
|
||||
public IList<TreeNode> GetChildren()
|
||||
{
|
||||
return new ReadOnlyCollection<TreeNode>(children);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a child to the list of children under this node
|
||||
/// </summary>
|
||||
/// <param name="newChild"><see cref="TreeNode"/></param>
|
||||
public void AddChild(TreeNode newChild)
|
||||
{
|
||||
Validate.IsNotNull(nameof(newChild), newChild);
|
||||
children.Add(newChild);
|
||||
newChild.Parent = this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optional context to help with lookup of children
|
||||
/// </summary>
|
||||
public virtual object GetContext()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to convert context to expected format
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type to convert to</typeparam>
|
||||
/// <returns>context as expected type of null if it doesn't match</returns>
|
||||
public T GetContextAs<T>()
|
||||
where T : class
|
||||
{
|
||||
return GetContext() as T;
|
||||
}
|
||||
|
||||
public T ParentAs<T>()
|
||||
where T : TreeNode
|
||||
{
|
||||
return Parent as T;
|
||||
}
|
||||
|
||||
protected void PopulateChildren()
|
||||
{
|
||||
Debug.Assert(IsAlwaysLeaf == false);
|
||||
|
||||
SmoQueryContext context = this.GetContextAs<SmoQueryContext>();
|
||||
|
||||
if (children.IsPopulating || context == null)
|
||||
return;
|
||||
|
||||
children.Clear();
|
||||
BeginChildrenInit();
|
||||
|
||||
try
|
||||
{
|
||||
IEnumerable<ChildFactory> childFactories = context.GetObjectExplorerService().GetApplicableChildFactories(this);
|
||||
if (childFactories != null)
|
||||
{
|
||||
foreach (var factory in childFactories)
|
||||
{
|
||||
IEnumerable<TreeNode> items = factory.Expand(this);
|
||||
if (items != null)
|
||||
{
|
||||
foreach (TreeNode item in items)
|
||||
{
|
||||
children.Add(item);
|
||||
item.Parent = this;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
EndChildrenInit();
|
||||
}
|
||||
}
|
||||
|
||||
public void BeginChildrenInit()
|
||||
{
|
||||
children.BeginInit();
|
||||
}
|
||||
|
||||
public void EndChildrenInit()
|
||||
{
|
||||
children.EndInit();
|
||||
// TODO consider use of deferred children and if it's necessary
|
||||
// children.EndInit(this, ref deferredChildren);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sort Priority to help when ordering elements in the tree
|
||||
/// </summary>
|
||||
public int? SortPriority { get; set; }
|
||||
|
||||
protected virtual int CompareSamePriorities(TreeNode thisItem, TreeNode otherItem)
|
||||
{
|
||||
return string.Compare(thisItem.NodeValue, otherItem.NodeValue, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public int CompareTo(TreeNode other)
|
||||
{
|
||||
|
||||
if (!this.SortPriority.HasValue &&
|
||||
!other.SortPriority.HasValue)
|
||||
{
|
||||
return CompareSamePriorities(this, other);
|
||||
}
|
||||
|
||||
if (this.SortPriority.HasValue &&
|
||||
!other.SortPriority.HasValue)
|
||||
{
|
||||
return -1; // this is above other
|
||||
}
|
||||
if (!this.SortPriority.HasValue)
|
||||
{
|
||||
return 1; // this is below other
|
||||
}
|
||||
|
||||
// Both have sort priority
|
||||
int priDiff = this.SortPriority.Value - other.SortPriority.Value;
|
||||
if (priDiff < 0)
|
||||
return -1; // this is below other
|
||||
if (priDiff == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
{
|
||||
public class TreeNodeWithContext
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates which type of server a given node type is valid for
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ValidForFlag
|
||||
{
|
||||
Sql2005 = 0x01,
|
||||
Sql2008 = 0x02,
|
||||
Sql2012 = 0x04,
|
||||
Sql2014 = 0x08,
|
||||
Azure = 0x10,
|
||||
NotDebugInstance = 0x20,
|
||||
NotContainedUser = 0x40,
|
||||
AzureV12 = 0x80,
|
||||
Sql2016 = 0x100,
|
||||
CanConnectToMaster = 0x200,
|
||||
CanViewSecurity = 0x400,
|
||||
SqlvNext = 0x800,
|
||||
All = Sql2005 | Sql2008 | Sql2012 | Sql2014 | Sql2016 | SqlvNext | Azure | AzureV12
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user