mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
Adding filtering support to OE (#2039)
* Init push * Fixing filters * Fixing more filters * Fixing display strings * Fixing boolean filter * Adding comments * Fixing function name * Making nullables * Separating filter parsing logic * Adding tests * Update src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerUtils.cs Co-authored-by: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> * Update src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerUtils.cs Co-authored-by: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> * Update src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/NodeInfo.cs Co-authored-by: Charles Gagnon <chgagnon@microsoft.com> * Update src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/NodeInfo.cs Co-authored-by: Charles Gagnon <chgagnon@microsoft.com> * Update src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs Co-authored-by: Charles Gagnon <chgagnon@microsoft.com> * Adding comments * Fixing whitespace * Adding more comments and changing to IEnumerable * Fixing code comments * Fixing tests adding more filters --------- Co-authored-by: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
This commit is contained in:
@@ -2381,6 +2381,134 @@ namespace Microsoft.SqlTools.ServiceLayer
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterName
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterName);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterNameDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterNameDescription);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterSchema
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterSchema);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterSchemaDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterSchemaDescription);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterOwner
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterOwner);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterOwnerDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterOwnerDescription);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterDurabilityType
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterDurabilityType);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterDurabilityTypeDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterDurabilityTypeDescription);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterIsMemoryOptimized
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterIsMemoryOptimized);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterIsMemoryOptimizedDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterIsMemoryOptimizedDescription);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterCreateDate
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterCreateDate);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterCreateDateDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterCreateDateDescription);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterIsNativelyCompiled
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterIsNativelyCompiled);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterIsNativelyCompiledDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterIsNativelyCompiledDescription);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterInPrimaryKey
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterInPrimaryKey);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FilterInPrimaryKeyDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FilterInPrimaryKeyDescription);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ScriptingParams_ConnectionString_Property_Invalid
|
||||
{
|
||||
get
|
||||
@@ -12045,6 +12173,54 @@ namespace Microsoft.SqlTools.ServiceLayer
|
||||
public const string DatabaseNotAccessible = "DatabaseNotAccessible";
|
||||
|
||||
|
||||
public const string FilterName = "FilterName";
|
||||
|
||||
|
||||
public const string FilterNameDescription = "FilterNameDescription";
|
||||
|
||||
|
||||
public const string FilterSchema = "FilterSchema";
|
||||
|
||||
|
||||
public const string FilterSchemaDescription = "FilterSchemaDescription";
|
||||
|
||||
|
||||
public const string FilterOwner = "FilterOwner";
|
||||
|
||||
|
||||
public const string FilterOwnerDescription = "FilterOwnerDescription";
|
||||
|
||||
|
||||
public const string FilterDurabilityType = "FilterDurabilityType";
|
||||
|
||||
|
||||
public const string FilterDurabilityTypeDescription = "FilterDurabilityTypeDescription";
|
||||
|
||||
|
||||
public const string FilterIsMemoryOptimized = "FilterIsMemoryOptimized";
|
||||
|
||||
|
||||
public const string FilterIsMemoryOptimizedDescription = "FilterIsMemoryOptimizedDescription";
|
||||
|
||||
|
||||
public const string FilterCreateDate = "FilterCreateDate";
|
||||
|
||||
|
||||
public const string FilterCreateDateDescription = "FilterCreateDateDescription";
|
||||
|
||||
|
||||
public const string FilterIsNativelyCompiled = "FilterIsNativelyCompiled";
|
||||
|
||||
|
||||
public const string FilterIsNativelyCompiledDescription = "FilterIsNativelyCompiledDescription";
|
||||
|
||||
|
||||
public const string FilterInPrimaryKey = "FilterInPrimaryKey";
|
||||
|
||||
|
||||
public const string FilterInPrimaryKeyDescription = "FilterInPrimaryKeyDescription";
|
||||
|
||||
|
||||
public const string ScriptingParams_ConnectionString_Property_Invalid = "ScriptingParams_ConnectionString_Property_Invalid";
|
||||
|
||||
|
||||
|
||||
@@ -1458,6 +1458,70 @@
|
||||
<value>The database {0} is not accessible.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterName" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterNameDescription" xml:space="preserve">
|
||||
<value>Include or exclude objects based on the name or part of a name.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterSchema" xml:space="preserve">
|
||||
<value>Schema</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterSchemaDescription" xml:space="preserve">
|
||||
<value> Include or exclude objects based on the schema or part of a schema name.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterOwner" xml:space="preserve">
|
||||
<value>Owner</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterOwnerDescription" xml:space="preserve">
|
||||
<value>Include or exclude objects based on the owner or part of an owner name.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterDurabilityType" xml:space="preserve">
|
||||
<value>Durability Type</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterDurabilityTypeDescription" xml:space="preserve">
|
||||
<value>Include or exclude objects based on the durability type.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterIsMemoryOptimized" xml:space="preserve">
|
||||
<value>Is Memory Optimized</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterIsMemoryOptimizedDescription" xml:space="preserve">
|
||||
<value>Include or exclude objects based on whether the object is memory optimized.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterCreateDate" xml:space="preserve">
|
||||
<value>Create Date</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterCreateDateDescription" xml:space="preserve">
|
||||
<value>Select or type a creation date to include or exclude objects created at any time on that date, or enter a starting and ending date to include or exclude objects created in that inclusive date range.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterIsNativelyCompiled" xml:space="preserve">
|
||||
<value>Is Natively Compiled</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterIsNativelyCompiledDescription" xml:space="preserve">
|
||||
<value>Include or exclude objects based on whether the object is natively compiled.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterInPrimaryKey" xml:space="preserve">
|
||||
<value>In Primary Key</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FilterInPrimaryKeyDescription" xml:space="preserve">
|
||||
<value>Include or exclude objects based on whether the column is in a primary key.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="ScriptingParams_ConnectionString_Property_Invalid" xml:space="preserve">
|
||||
<value>Error parsing ScriptingParams.ConnectionString property.</value>
|
||||
<comment></comment>
|
||||
|
||||
@@ -720,6 +720,22 @@ FileTable_LabelPart = File Table
|
||||
|
||||
DatabaseNotAccessible = The database {0} is not accessible.
|
||||
|
||||
FilterName = Name
|
||||
FilterNameDescription = Include or exclude objects based on the name or part of a name.
|
||||
FilterSchema = Schema
|
||||
FilterSchemaDescription = Include or exclude objects based on the schema or part of a schema name.
|
||||
FilterOwner = Owner
|
||||
FilterOwnerDescription = Include or exclude objects based on the owner or part of an owner name.
|
||||
FilterDurabilityType = Durability Type
|
||||
FilterDurabilityTypeDescription = Include or exclude objects based on the durability type.
|
||||
FilterIsMemoryOptimized = Is Memory Optimized
|
||||
FilterIsMemoryOptimizedDescription = Include or exclude objects based on whether the object is memory optimized.
|
||||
FilterCreateDate = Create Date
|
||||
FilterCreateDateDescription = Select or type a creation date to include or exclude objects created at any time on that date, or enter a starting and ending date to include or exclude objects created in that inclusive date range.
|
||||
FilterIsNativelyCompiled = Is Natively Compiled
|
||||
FilterIsNativelyCompiledDescription = Include or exclude objects based on whether the object is natively compiled.
|
||||
FilterInPrimaryKey = In Primary Key
|
||||
FilterInPrimaryKeyDescription = Include or exclude objects based on whether the column is in a primary key.
|
||||
|
||||
############################################################################
|
||||
# Scripting Service
|
||||
|
||||
@@ -7137,6 +7137,76 @@ The Query Processor estimates that implementing the following index could improv
|
||||
<target state="new">Impersonate Any Login</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterName">
|
||||
<source>Name</source>
|
||||
<target state="new">Name</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterNameDescription">
|
||||
<source>Include or exclude objects based on the name or part of a name.</source>
|
||||
<target state="new">Include or exclude objects based on the name or part of a name.</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterSchema">
|
||||
<source>Schema</source>
|
||||
<target state="new">Schema</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterSchemaDescription">
|
||||
<source> Include or exclude objects based on the schema or part of a schema name.</source>
|
||||
<target state="new"> Include or exclude objects based on the schema or part of a schema name.</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterOwner">
|
||||
<source>Owner</source>
|
||||
<target state="new">Owner</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterOwnerDescription">
|
||||
<source>Include or exclude objects based on the owner or part of an owner name.</source>
|
||||
<target state="new">Include or exclude objects based on the owner or part of an owner name.</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterDurabilityType">
|
||||
<source>Durability Type</source>
|
||||
<target state="new">Durability Type</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterDurabilityTypeDescription">
|
||||
<source>Include or exclude objects based on the durability type.</source>
|
||||
<target state="new">Include or exclude objects based on the durability type.</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterIsMemoryOptimized">
|
||||
<source>Is Memory Optimized</source>
|
||||
<target state="new">Is Memory Optimized</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterIsMemoryOptimizedDescription">
|
||||
<source>Include or exclude objects based on whether the object is memory optimized.</source>
|
||||
<target state="new">Include or exclude objects based on whether the object is memory optimized.</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterCreateDate">
|
||||
<source>Create Date</source>
|
||||
<target state="new">Create Date</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterCreateDateDescription">
|
||||
<source>Select or type a creation date to include or exclude objects created at any time on that date, or enter a starting and ending date to include or exclude objects created in that inclusive date range.</source>
|
||||
<target state="new">Select or type a creation date to include or exclude objects created at any time on that date, or enter a starting and ending date to include or exclude objects created in that inclusive date range.</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterIsNativelyCompiled">
|
||||
<source>Is Natively Compiled</source>
|
||||
<target state="new">Is Natively Compiled</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterIsNativelyCompiledDescription">
|
||||
<source>Include or exclude objects based on whether the object is natively compiled.</source>
|
||||
<target state="new">Include or exclude objects based on whether the object is natively compiled.</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="ServiceProviderNotSet">
|
||||
<source>SetServiceProvider() was not called to establish the required service provider</source>
|
||||
<target state="new">SetServiceProvider() was not called to establish the required service provider</target>
|
||||
@@ -7147,6 +7217,16 @@ The Query Processor estimates that implementing the following index could improv
|
||||
<target state="new">Service {0} was not found in the service provider</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterInPrimaryKey">
|
||||
<source>In Primary Key</source>
|
||||
<target state="new">In Primary Key</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FilterInPrimaryKeyDescription">
|
||||
<source>Include or exclude objects based on whether the column is in a primary key.</source>
|
||||
<target state="new">Include or exclude objects based on whether the column is in a primary key.</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
@@ -57,6 +57,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts
|
||||
/// Security token for AzureMFA authentication for refresing access token on connection.
|
||||
/// </summary>
|
||||
public SecurityToken? SecurityToken { get; set; }
|
||||
|
||||
///<summary>
|
||||
/// Filters to apply to the expand request
|
||||
///</summary>
|
||||
public NodeFilter[]? Filters { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#nullable disable
|
||||
|
||||
using Microsoft.SqlTools.ServiceLayer.Metadata.Contracts;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts
|
||||
{
|
||||
@@ -71,5 +72,86 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts
|
||||
/// The object type of the node. e.g. Database, Server, Tables...
|
||||
/// </summary>
|
||||
public string ObjectType { get; set; }
|
||||
/// <summary>
|
||||
/// Filterable properties that this node supports
|
||||
/// </summary>
|
||||
public NodeFilterProperty[] FilterableProperties { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The filterable properties that a node supports
|
||||
/// </summary>
|
||||
public class NodeFilterProperty
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the filter property
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// The name of the filter property displayed to the user
|
||||
/// </summary>
|
||||
public string DisplayName { get; set; }
|
||||
/// <summary>
|
||||
/// The description of the filter property
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
/// <summary>
|
||||
/// The data type of the filter property
|
||||
/// </summary>
|
||||
public NodeFilterPropertyDataType Type { get; set; }
|
||||
/// <summary>
|
||||
/// The list of choices for the filter property if the type is choice
|
||||
/// </summary>
|
||||
public string[] Choices { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The data type of the filter property. Matches NodeFilterPropertyDataType enum in ADS : https://github.com/microsoft/azuredatastudio/blob/main/src/sql/azdata.proposed.d.ts#L1847-L1853
|
||||
/// </summary>
|
||||
public enum NodeFilterPropertyDataType
|
||||
{
|
||||
String = 0,
|
||||
Number = 1,
|
||||
Boolean = 2,
|
||||
Date = 3,
|
||||
Choice = 4
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The operator of the filter property. Matches NodeFilterOperator enum in ADS: https://github.com/microsoft/azuredatastudio/blob/main/src/sql/azdata.proposed.d.ts#L1855-L1868
|
||||
/// </summary>
|
||||
public enum NodeFilterOperator
|
||||
{
|
||||
Equals = 0,
|
||||
NotEquals = 1,
|
||||
LessThan = 2,
|
||||
LessThanOrEquals = 3,
|
||||
GreaterThan = 4,
|
||||
GreaterThanOrEquals = 5,
|
||||
Between = 6,
|
||||
NotBetween = 7,
|
||||
Contains = 8,
|
||||
NotContains = 9,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The filters that can be used to filter the nodes in an expand request.
|
||||
/// </summary>
|
||||
public class NodeFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the filter property
|
||||
/// </summary>
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The operator of the filter property
|
||||
/// </summary>
|
||||
public NodeFilterOperator Operator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The applied values of the filter property
|
||||
/// </summary>
|
||||
public JToken Value { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
@@ -31,9 +32,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
/// </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);
|
||||
/// <param name="name">name of the sql object to filter</param>
|
||||
/// <param name="includeSystemObjects">include system objects</param>
|
||||
/// <param name="cancellationToken">cancellation token</param>
|
||||
/// <param name="filters">filters to apply</param>
|
||||
public abstract IEnumerable<TreeNode> Expand(TreeNode parent, bool refresh, string name, bool includeSystemObjects, CancellationToken cancellationToken, IEnumerable<NodeFilter>? filters);
|
||||
|
||||
/// <summary>
|
||||
/// The list of filters that should be applied on the smo object list
|
||||
|
||||
@@ -46,6 +46,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
/// </summary>
|
||||
public bool IsNotFilter { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the values are for type datetime
|
||||
/// </summary>
|
||||
public bool IsDateTime { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the type of the filter. It can be EQUALS, DATETIME, FALSE or CONTAINS
|
||||
/// More information can be found here:
|
||||
@@ -82,7 +87,97 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
}
|
||||
|
||||
StringBuilder filter = new StringBuilder();
|
||||
|
||||
|
||||
foreach (var value in Values)
|
||||
{
|
||||
string filterText = string.Empty;
|
||||
if (IsDateTime)
|
||||
{
|
||||
string Value1;
|
||||
string Value2;
|
||||
switch (FilterType)
|
||||
{
|
||||
case FilterType.BETWEEN:
|
||||
string[] betweenValues = (string[])value;
|
||||
Value1 = DateTime.Parse((string)betweenValues[0]).ToString("yyyy-MM-dd 00:00:00.000");
|
||||
Value2 = DateTime.Parse((string)betweenValues[1]).ToString("yyyy-MM-dd 23:59:59.999");
|
||||
filterText = $"@{Property} >= datetime('{Value1}') and @{Property} <= datetime('{Value2}')";
|
||||
break;
|
||||
case FilterType.NOTBETWEEN:
|
||||
IsNotFilter = true;
|
||||
string[] notBetweenValues = (string[])value;
|
||||
Value1 = DateTime.Parse((string)notBetweenValues[0]).ToString("yyyy-MM-dd 00:00:00.000");
|
||||
Value2 = DateTime.Parse((string)notBetweenValues[1]).ToString("yyyy-MM-dd 23:59:59.999");
|
||||
filterText = $"@{Property} >= datetime('{Value1}') and @{Property} <= datetime('{Value2}')";
|
||||
break;
|
||||
case FilterType.EQUALS:
|
||||
Value1 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 00:00:00.000");
|
||||
Value2 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 23:59:59.999");
|
||||
filterText = $"@{Property} >= datetime('{Value1}') and @{Property} <= datetime('{Value2}')";
|
||||
break;
|
||||
case FilterType.GREATERTHAN:
|
||||
Value1 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 23:59:59.999");
|
||||
filterText = $"@{Property} > datetime('{Value1}')";
|
||||
break;
|
||||
case FilterType.LESSTHAN:
|
||||
Value1 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 00:00:00.000");
|
||||
filterText = $"@{Property} < datetime('{Value1}')";
|
||||
break;
|
||||
case FilterType.GREATERTHANOREQUAL:
|
||||
Value1 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 00:00:00.000");
|
||||
filterText = $"@{Property} >= datetime('{Value1}')";
|
||||
break;
|
||||
case FilterType.LESSTHANOREQUAL:
|
||||
Value1 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 23:59:59.999");
|
||||
filterText = $"@{Property} <= datetime('{Value1}')";
|
||||
break;
|
||||
case FilterType.NOTEQUALS:
|
||||
IsNotFilter = true;
|
||||
Value1 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 00:00:00.000");
|
||||
Value2 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 23:59:59.999");
|
||||
filterText = $"@{Property} >= datetime('{Value1}') and @{Property} <= datetime('{Value2}')";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (IsNumericType(Type))
|
||||
{
|
||||
switch (FilterType)
|
||||
{
|
||||
case FilterType.BETWEEN:
|
||||
object[] betweenValues = (object[])value;
|
||||
filterText = $"@{Property} >= {Decimal.Parse(betweenValues[0].ToString())} and @{Property} <= {Decimal.Parse(betweenValues[1].ToString())}";
|
||||
break;
|
||||
case FilterType.NOTBETWEEN:
|
||||
IsNotFilter = true;
|
||||
object[] notBetweenValues = (object[])value;
|
||||
filterText = $"@{Property} >= {Decimal.Parse(notBetweenValues[0].ToString())} and @{Property} <= {Decimal.Parse(notBetweenValues[1].ToString())}";
|
||||
break;
|
||||
case FilterType.EQUALS:
|
||||
filterText = $"@{Property} = {Decimal.Parse(value.ToString())}";
|
||||
break;
|
||||
case FilterType.GREATERTHAN:
|
||||
filterText = $"@{Property} > {Decimal.Parse(value.ToString())}";
|
||||
break;
|
||||
case FilterType.LESSTHAN:
|
||||
filterText = $"@{Property} < {Decimal.Parse(value.ToString())}";
|
||||
break;
|
||||
case FilterType.GREATERTHANOREQUAL:
|
||||
filterText = $"@{Property} >= {Decimal.Parse(value.ToString())}";
|
||||
break;
|
||||
case FilterType.LESSTHANOREQUAL:
|
||||
filterText = $"@{Property} <= {Decimal.Parse(value.ToString())}";
|
||||
break;
|
||||
case FilterType.NOTEQUALS:
|
||||
filterText = $"@{Property} != {Decimal.Parse(value.ToString())}";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
object propertyValue = value;
|
||||
if (Type == typeof(string))
|
||||
@@ -93,13 +188,26 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
{
|
||||
propertyValue = (int)Convert.ChangeType(value, Type);
|
||||
}
|
||||
|
||||
string filterText = string.Empty;
|
||||
switch (FilterType)
|
||||
{
|
||||
case FilterType.EQUALS:
|
||||
filterText = $"@{Property} = {propertyValue}";
|
||||
break;
|
||||
case FilterType.NOTEQUALS:
|
||||
filterText = $"@{Property} != {propertyValue}";
|
||||
break;
|
||||
case FilterType.LESSTHAN:
|
||||
filterText = $"@{Property} < {propertyValue}";
|
||||
break;
|
||||
case FilterType.GREATERTHAN:
|
||||
filterText = $"@{Property} > {propertyValue}";
|
||||
break;
|
||||
case FilterType.LESSTHANOREQUAL:
|
||||
filterText = $"@{Property} <= {propertyValue}";
|
||||
break;
|
||||
case FilterType.GREATERTHANOREQUAL:
|
||||
filterText = $"@{Property} >= {propertyValue}";
|
||||
break;
|
||||
case FilterType.DATETIME:
|
||||
filterText = $"@{Property} = datetime({propertyValue})";
|
||||
break;
|
||||
@@ -113,6 +221,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
filterText = $"isnull(@{Property})";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string orPrefix = filter.Length == 0 ? string.Empty : " or ";
|
||||
if (IsNotFilter)
|
||||
@@ -131,6 +240,27 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public static bool IsNumericType(Type type)
|
||||
{
|
||||
switch (Type.GetTypeCode(type))
|
||||
{
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.UInt64:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.Int64:
|
||||
case TypeCode.Decimal:
|
||||
case TypeCode.Double:
|
||||
case TypeCode.Single:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum FilterType
|
||||
@@ -139,6 +269,13 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
DATETIME,
|
||||
CONTAINS,
|
||||
FALSE,
|
||||
ISNULL
|
||||
ISNULL,
|
||||
NOTEQUALS,
|
||||
LESSTHAN,
|
||||
GREATERTHAN,
|
||||
LESSTHANOREQUAL,
|
||||
GREATERTHANOREQUAL,
|
||||
BETWEEN,
|
||||
NOTBETWEEN
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
/// </summary>
|
||||
public string NodeStatus { get; set; }
|
||||
|
||||
public NodeFilterProperty[] FilterProperties { 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
|
||||
@@ -235,7 +237,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
NodeStatus = this.NodeStatus,
|
||||
NodeSubType = this.NodeSubType,
|
||||
ErrorMessage = this.ErrorMessage,
|
||||
ObjectType = this.NodeTypeId.ToString()
|
||||
ObjectType = this.NodeTypeId.ToString(),
|
||||
FilterableProperties = this.FilterProperties
|
||||
};
|
||||
}
|
||||
|
||||
@@ -243,14 +246,14 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
/// 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(string name, CancellationToken cancellationToken, string? accessToken = null)
|
||||
public IList<TreeNode> Expand(string name, CancellationToken cancellationToken, string? accessToken = null, IEnumerable<NodeFilter>? filters = null)
|
||||
{
|
||||
// TODO consider why solution explorer has separate Children and Items options
|
||||
if (children.IsInitialized)
|
||||
{
|
||||
return children;
|
||||
}
|
||||
PopulateChildren(false, name, cancellationToken, accessToken);
|
||||
PopulateChildren(false, name, cancellationToken, accessToken, filters);
|
||||
return children;
|
||||
}
|
||||
|
||||
@@ -258,19 +261,19 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
/// 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(CancellationToken cancellationToken, string? accessToken = null)
|
||||
public IList<TreeNode> Expand(CancellationToken cancellationToken, string? accessToken = null, IEnumerable<NodeFilter>? filters = null)
|
||||
{
|
||||
return Expand(null, cancellationToken, accessToken);
|
||||
return Expand(null, cancellationToken, accessToken, filters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh this node and returns its children
|
||||
/// </summary>
|
||||
/// <returns>Children as an IList. This is the raw children collection, not a copy</returns>
|
||||
public virtual IList<TreeNode> Refresh(CancellationToken cancellationToken, string? accessToken = null)
|
||||
public virtual IList<TreeNode> Refresh(CancellationToken cancellationToken, string? accessToken = null, IEnumerable<NodeFilter>? filters = null)
|
||||
{
|
||||
// TODO consider why solution explorer has separate Children and Items options
|
||||
PopulateChildren(true, null, cancellationToken, accessToken);
|
||||
PopulateChildren(true, null, cancellationToken, accessToken, filters);
|
||||
return children;
|
||||
}
|
||||
|
||||
@@ -322,7 +325,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
return Parent as T;
|
||||
}
|
||||
|
||||
protected virtual void PopulateChildren(bool refresh, string name, CancellationToken cancellationToken, string? accessToken = null)
|
||||
protected virtual void PopulateChildren(bool refresh, string name, CancellationToken cancellationToken, string? accessToken = null, IEnumerable<NodeFilter>? filters = null)
|
||||
{
|
||||
Logger.Write(TraceEventType.Verbose, string.Format(CultureInfo.InvariantCulture, "Populating oe node :{0}", this.GetNodePath()));
|
||||
Debug.Assert(IsAlwaysLeaf == false);
|
||||
@@ -353,7 +356,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
try
|
||||
{
|
||||
Logger.Verbose($"Begin populate children for {this.GetNodePath()} using {factory.GetType()} factory");
|
||||
IEnumerable<TreeNode> items = factory.Expand(this, refresh, name, includeSystemObjects, cancellationToken);
|
||||
IEnumerable<TreeNode> items = factory.Expand(this, refresh, name, includeSystemObjects, cancellationToken, filters);
|
||||
Logger.Verbose($"End populate children for {this.GetNodePath()} using {factory.GetType()} factory");
|
||||
if (items != null)
|
||||
{
|
||||
|
||||
@@ -378,12 +378,12 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
|
||||
|
||||
}
|
||||
|
||||
internal Task<ExpandResponse> ExpandNode(ObjectExplorerSession session, string nodePath, bool forceRefresh = false, SecurityToken? securityToken = null)
|
||||
internal Task<ExpandResponse> ExpandNode(ObjectExplorerSession session, string nodePath, bool forceRefresh = false, SecurityToken? securityToken = null, NodeFilter[]? filters = null)
|
||||
{
|
||||
return Task.Run(() => QueueExpandNodeRequest(session, nodePath, forceRefresh, securityToken));
|
||||
return Task.Run(() => QueueExpandNodeRequest(session, nodePath, forceRefresh, securityToken, filters));
|
||||
}
|
||||
|
||||
internal ExpandResponse QueueExpandNodeRequest(ObjectExplorerSession session, string nodePath, bool forceRefresh = false, SecurityToken? securityToken = null)
|
||||
internal ExpandResponse QueueExpandNodeRequest(ObjectExplorerSession session, string nodePath, bool forceRefresh = false, SecurityToken? securityToken = null, NodeFilter[]? filters = null)
|
||||
{
|
||||
NodeInfo[] nodes = null;
|
||||
TreeNode? node = session.Root.FindNodeByPath(nodePath);
|
||||
@@ -448,12 +448,12 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
|
||||
if (forceRefresh)
|
||||
{
|
||||
Logger.Verbose($"Forcing refresh for {nodePath}");
|
||||
nodes = node.Refresh(cancelToken, securityToken?.Token).Select(x => x.ToNodeInfo()).ToArray();
|
||||
nodes = node.Refresh(cancelToken, securityToken?.Token, filters).Select(x => x.ToNodeInfo()).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Verbose($"Expanding {nodePath}");
|
||||
nodes = node.Expand(cancelToken, securityToken?.Token).Select(x => x.ToNodeInfo()).ToArray();
|
||||
nodes = node.Expand(cancelToken, securityToken?.Token, filters).Select(x => x.ToNodeInfo()).ToArray();
|
||||
}
|
||||
response.Nodes = nodes;
|
||||
response.ErrorMessage = node.ErrorMessage;
|
||||
@@ -649,7 +649,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
|
||||
private async Task ExpandNodeAsync(ObjectExplorerSession session, ExpandParams expandParams, CancellationToken cancellationToken, bool forceRefresh = false)
|
||||
{
|
||||
ExpandResponse response = null;
|
||||
response = await ExpandNode(session, expandParams.NodePath, forceRefresh, expandParams.SecurityToken);
|
||||
response = await ExpandNode(session, expandParams.NodePath, forceRefresh, expandParams.SecurityToken, expandParams.Filters);
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
Logger.Write(TraceEventType.Verbose, "OE expand canceled");
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
|
||||
{
|
||||
@@ -53,7 +55,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
|
||||
/// <returns>A Tree Node that matches the condition, or null if no matching node could be found</returns>
|
||||
public static TreeNode? FindNode(TreeNode node, Predicate<TreeNode> condition, Predicate<TreeNode> filter, bool expandIfNeeded = false)
|
||||
{
|
||||
if(node == null)
|
||||
if (node == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -76,5 +78,95 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static INodeFilter ConvertExpandNodeFilterToNodeFilter(NodeFilter filter, NodeFilterProperty filterProperty)
|
||||
{
|
||||
Type type = typeof(string);
|
||||
|
||||
var IsDateTime = filterProperty.Type == NodeFilterPropertyDataType.Date;
|
||||
|
||||
FilterType filterType = FilterType.EQUALS;
|
||||
bool isNotFilter = false;
|
||||
|
||||
object filterValue = null;
|
||||
|
||||
switch (filterProperty.Type)
|
||||
{
|
||||
case NodeFilterPropertyDataType.String:
|
||||
case NodeFilterPropertyDataType.Date:
|
||||
case NodeFilterPropertyDataType.Choice:
|
||||
type = typeof(string);
|
||||
filterValue = filter.Value.ToString();
|
||||
break;
|
||||
case NodeFilterPropertyDataType.Number:
|
||||
type = typeof(int);
|
||||
filterValue = filter.Value.ToObject<int>();
|
||||
break;
|
||||
case NodeFilterPropertyDataType.Boolean:
|
||||
type = typeof(bool);
|
||||
filterValue = filter.Value.ToObject<bool>() ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (filter.Operator)
|
||||
{
|
||||
case NodeFilterOperator.Equals:
|
||||
filterType = FilterType.EQUALS;
|
||||
break;
|
||||
case NodeFilterOperator.NotEquals:
|
||||
filterType = FilterType.EQUALS;
|
||||
isNotFilter = true;
|
||||
break;
|
||||
case NodeFilterOperator.LessThan:
|
||||
filterType = FilterType.LESSTHAN;
|
||||
break;
|
||||
case NodeFilterOperator.LessThanOrEquals:
|
||||
filterType = FilterType.LESSTHANOREQUAL;
|
||||
break;
|
||||
case NodeFilterOperator.GreaterThan:
|
||||
filterType = FilterType.GREATERTHAN;
|
||||
break;
|
||||
case NodeFilterOperator.GreaterThanOrEquals:
|
||||
filterType = FilterType.GREATERTHANOREQUAL;
|
||||
break;
|
||||
case NodeFilterOperator.Contains:
|
||||
filterType = FilterType.CONTAINS;
|
||||
break;
|
||||
case NodeFilterOperator.NotContains:
|
||||
filterType = FilterType.CONTAINS;
|
||||
isNotFilter = true;
|
||||
break;
|
||||
case NodeFilterOperator.Between:
|
||||
filterType = FilterType.BETWEEN;
|
||||
break;
|
||||
case NodeFilterOperator.NotBetween:
|
||||
filterType = FilterType.NOTBETWEEN;
|
||||
isNotFilter = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (filter.Operator == NodeFilterOperator.Between || filter.Operator == NodeFilterOperator.NotBetween)
|
||||
{
|
||||
if (filterProperty.Type == NodeFilterPropertyDataType.Number)
|
||||
{
|
||||
filterValue = filter.Value.ToObject<int[]>();
|
||||
}
|
||||
else if (filterProperty.Type == NodeFilterPropertyDataType.Date)
|
||||
{
|
||||
filterValue = filter.Value.ToObject<string[]>();
|
||||
}
|
||||
}
|
||||
|
||||
return new NodePropertyFilter
|
||||
{
|
||||
Property = filterProperty.Name,
|
||||
Type = type,
|
||||
Values = new List<object> { filterValue },
|
||||
IsNotFilter = isNotFilter,
|
||||
FilterType = filterType,
|
||||
IsDateTime = IsDateTime
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
@@ -54,12 +56,12 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
}
|
||||
}
|
||||
|
||||
protected override void PopulateChildren(bool refresh, string name, CancellationToken cancellationToken, string? accessToken = null)
|
||||
protected override void PopulateChildren(bool refresh, string name, CancellationToken cancellationToken, string? accessToken = null, IEnumerable<NodeFilter>? filters = null)
|
||||
{
|
||||
var smoQueryContext = this.GetContextAs<SmoQueryContext>();
|
||||
if (IsAccessible(smoQueryContext))
|
||||
{
|
||||
base.PopulateChildren(refresh, name, cancellationToken, accessToken);
|
||||
base.PopulateChildren(refresh, name, cancellationToken, accessToken, filters);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
@@ -20,12 +21,13 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
public class SmoChildFactoryBase : 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)
|
||||
public override IEnumerable<TreeNode> Expand(TreeNode parent, bool refresh, string name, bool includeSystemObjects, CancellationToken cancellationToken, IEnumerable<NodeFilter>? filters = null)
|
||||
{
|
||||
List<TreeNode> allChildren = new List<TreeNode>();
|
||||
|
||||
@@ -33,7 +35,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
if (this.PutFoldersAfterNodes)
|
||||
{
|
||||
OnExpandPopulateNonFolders(allChildren, parent, refresh, name, cancellationToken);
|
||||
OnExpandPopulateNonFolders(allChildren, parent, refresh, name, cancellationToken, filters);
|
||||
OnExpandPopulateFoldersAndFilter(allChildren, parent, includeSystemObjects);
|
||||
RemoveFoldersFromInvalidSqlServerVersions(allChildren, parent);
|
||||
}
|
||||
@@ -41,7 +43,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
OnExpandPopulateFoldersAndFilter(allChildren, parent, includeSystemObjects);
|
||||
RemoveFoldersFromInvalidSqlServerVersions(allChildren, parent);
|
||||
OnExpandPopulateNonFolders(allChildren, parent, refresh, name, cancellationToken);
|
||||
OnExpandPopulateNonFolders(allChildren, parent, refresh, name, cancellationToken, filters);
|
||||
}
|
||||
|
||||
OnBeginAsyncOperations(parent);
|
||||
@@ -110,7 +112,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
/// </summary>
|
||||
/// <param name="allChildren">List to which nodes should be added</param>
|
||||
/// <param name="parent">Parent the nodes are being added to</param>
|
||||
protected virtual void OnExpandPopulateNonFolders(IList<TreeNode> allChildren, TreeNode parent, bool refresh, string name, CancellationToken cancellationToken)
|
||||
protected virtual void OnExpandPopulateNonFolders(IList<TreeNode> allChildren, TreeNode parent, bool refresh, string name, CancellationToken cancellationToken, IEnumerable<NodeFilter>? appliedFilters = null)
|
||||
{
|
||||
Logger.Write(TraceEventType.Verbose, string.Format(CultureInfo.InvariantCulture, "child factory parent :{0}", parent.GetNodePath()));
|
||||
|
||||
@@ -131,6 +133,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
IEnumerable<SmoQuerier> queriers = context.ServiceProvider.GetServices<SmoQuerier>(IsCompatibleQuerier);
|
||||
var filters = this.Filters.ToList();
|
||||
var smoProperties = this.SmoProperties.Where(p => ServerVersionHelper.IsValidFor(serverValidFor, p.ValidFor)).Select(x => x.Name);
|
||||
var filterDefinitions = parent.FilterProperties;
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
filters.Add(new NodePropertyFilter
|
||||
@@ -140,6 +143,15 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
Values = new List<object> { name },
|
||||
});
|
||||
}
|
||||
if (appliedFilters != null)
|
||||
{
|
||||
foreach (var f in appliedFilters)
|
||||
{
|
||||
NodeFilterProperty filterProperty = filterDefinitions.FirstOrDefault(x => x.DisplayName == f.DisplayName);
|
||||
filters.Add(ObjectExplorerUtils.ConvertExpandNodeFilterToNodeFilter(f, filterProperty));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var querier in queriers)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
@@ -14,9 +14,11 @@ using System.Collections.Generic;
|
||||
using System.Composition;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace;
|
||||
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
|
||||
@@ -176,6 +178,30 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
NodeTypeId = NodeTypes.Databases,
|
||||
IsSystemObject = false,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
currentChildren.Add(new FolderNode {
|
||||
NodeValue = SR.SchemaHierarchy_Security,
|
||||
@@ -761,6 +787,55 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
NodeTypeId = NodeTypes.Tables,
|
||||
IsSystemObject = false,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Schema",
|
||||
DisplayName = SR.FilterSchema,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterSchemaDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "DurabilityType",
|
||||
DisplayName = SR.FilterDurabilityType,
|
||||
Type = NodeFilterPropertyDataType.Choice,
|
||||
Description = SR.FilterDurabilityTypeDescription,
|
||||
Choices = new string[] {
|
||||
"SchemaAndData",
|
||||
"SchemaOnly",
|
||||
}
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "IsMemoryOptimized",
|
||||
DisplayName = SR.FilterIsMemoryOptimized,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterIsMemoryOptimizedDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.SqlTools.ObjectExplorer.GroupBySchema)
|
||||
@@ -770,6 +845,37 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
NodeTypeId = NodeTypes.Views,
|
||||
IsSystemObject = false,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Schema",
|
||||
DisplayName = SR.FilterSchema,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterSchemaDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.SqlTools.ObjectExplorer.GroupBySchema)
|
||||
@@ -951,12 +1057,92 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
NodeTypeId = NodeTypes.Tables,
|
||||
IsSystemObject = false,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Schema",
|
||||
DisplayName = SR.FilterSchema,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterSchemaDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "DurabilityType",
|
||||
DisplayName = SR.FilterDurabilityType,
|
||||
Type = NodeFilterPropertyDataType.Choice,
|
||||
Description = SR.FilterDurabilityTypeDescription,
|
||||
Choices = new string[] {
|
||||
"SchemaAndData",
|
||||
"SchemaOnly",
|
||||
}
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "IsMemoryOptimized",
|
||||
DisplayName = SR.FilterIsMemoryOptimized,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterIsMemoryOptimizedDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
currentChildren.Add(new FolderNode {
|
||||
NodeValue = SR.SchemaHierarchy_Views,
|
||||
NodeTypeId = NodeTypes.Views,
|
||||
IsSystemObject = false,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Schema",
|
||||
DisplayName = SR.FilterSchema,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterSchemaDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
currentChildren.Add(new FolderNode {
|
||||
NodeValue = SR.SchemaHierarchy_Synonyms,
|
||||
@@ -1094,6 +1280,55 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
IsSystemObject = true,
|
||||
IsMsShippedOwned = true,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Schema",
|
||||
DisplayName = SR.FilterSchema,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterSchemaDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "DurabilityType",
|
||||
DisplayName = SR.FilterDurabilityType,
|
||||
Type = NodeFilterPropertyDataType.Choice,
|
||||
Description = SR.FilterDurabilityTypeDescription,
|
||||
Choices = new string[] {
|
||||
"SchemaAndData",
|
||||
"SchemaOnly",
|
||||
}
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "IsMemoryOptimized",
|
||||
DisplayName = SR.FilterIsMemoryOptimized,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterIsMemoryOptimizedDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
currentChildren.Add(new FolderNode {
|
||||
NodeValue = SR.SchemaHierarchy_DroppedLedgerTables,
|
||||
@@ -1101,6 +1336,55 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
IsSystemObject = false,
|
||||
ValidFor = ValidForFlag.Sql2022OrHigher|ValidForFlag.AzureV12,
|
||||
SortPriority = Int32.MaxValue,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Schema",
|
||||
DisplayName = SR.FilterSchema,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterSchemaDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "DurabilityType",
|
||||
DisplayName = SR.FilterDurabilityType,
|
||||
Type = NodeFilterPropertyDataType.Choice,
|
||||
Description = SR.FilterDurabilityTypeDescription,
|
||||
Choices = new string[] {
|
||||
"SchemaAndData",
|
||||
"SchemaOnly",
|
||||
}
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "IsMemoryOptimized",
|
||||
DisplayName = SR.FilterIsMemoryOptimized,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterIsMemoryOptimizedDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1178,6 +1462,37 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
IsMsShippedOwned = true,
|
||||
ValidFor = ValidForFlag.Sql2022OrHigher|ValidForFlag.AzureV12,
|
||||
SortPriority = Int32.MaxValue,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Schema",
|
||||
DisplayName = SR.FilterSchema,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterSchemaDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1236,6 +1551,44 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
NodeTypeId = NodeTypes.StoredProcedures,
|
||||
IsSystemObject = false,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Schema",
|
||||
DisplayName = SR.FilterSchema,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterSchemaDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "IsNativelyCompiled",
|
||||
DisplayName = SR.FilterIsNativelyCompiled,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterIsNativelyCompiledDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.SqlTools.ObjectExplorer.GroupBySchema)
|
||||
@@ -1280,6 +1633,37 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
IsSystemObject = false,
|
||||
ValidFor = ValidForFlag.Sql2012OrHigher|ValidForFlag.AzureV12,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Schema",
|
||||
DisplayName = SR.FilterSchema,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterSchemaDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1306,6 +1690,44 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
NodeTypeId = NodeTypes.StoredProcedures,
|
||||
IsSystemObject = false,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Schema",
|
||||
DisplayName = SR.FilterSchema,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterSchemaDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "IsNativelyCompiled",
|
||||
DisplayName = SR.FilterIsNativelyCompiled,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterIsNativelyCompiledDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
currentChildren.Add(new FolderNode {
|
||||
NodeValue = SR.SchemaHierarchy_Functions,
|
||||
@@ -1327,6 +1749,37 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
IsSystemObject = false,
|
||||
ValidFor = ValidForFlag.Sql2012OrHigher|ValidForFlag.AzureV12,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Schema",
|
||||
DisplayName = SR.FilterSchema,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterSchemaDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1747,6 +2200,23 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
NodeTypeId = NodeTypes.Columns,
|
||||
IsSystemObject = false,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "InPrimaryKey",
|
||||
DisplayName = SR.FilterInPrimaryKey,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterInPrimaryKeyDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
currentChildren.Add(new FolderNode {
|
||||
NodeValue = SR.SchemaHierarchy_Keys,
|
||||
@@ -1774,6 +2244,23 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
IsSystemObject = false,
|
||||
ValidFor = ValidForFlag.NotSqlDemand,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "IsMemoryOptimized",
|
||||
DisplayName = SR.FilterIsMemoryOptimized,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterIsMemoryOptimizedDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
currentChildren.Add(new FolderNode {
|
||||
NodeValue = SR.SchemaHierarchy_Statistics,
|
||||
@@ -1813,6 +2300,23 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
NodeTypeId = NodeTypes.Columns,
|
||||
IsSystemObject = false,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "InPrimaryKey",
|
||||
DisplayName = SR.FilterInPrimaryKey,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterInPrimaryKeyDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
currentChildren.Add(new FolderNode {
|
||||
NodeValue = SR.SchemaHierarchy_Constraints,
|
||||
@@ -1826,6 +2330,23 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
IsSystemObject = false,
|
||||
ValidFor = ValidForFlag.NotSqlDemand,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "IsMemoryOptimized",
|
||||
DisplayName = SR.FilterIsMemoryOptimized,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterIsMemoryOptimizedDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
currentChildren.Add(new FolderNode {
|
||||
NodeValue = SR.SchemaHierarchy_Statistics,
|
||||
@@ -1867,6 +2388,23 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
NodeTypeId = NodeTypes.Columns,
|
||||
IsSystemObject = false,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "InPrimaryKey",
|
||||
DisplayName = SR.FilterInPrimaryKey,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterInPrimaryKeyDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
currentChildren.Add(new FolderNode {
|
||||
NodeValue = SR.SchemaHierarchy_Statistics,
|
||||
@@ -2238,6 +2776,23 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
NodeTypeId = NodeTypes.Columns,
|
||||
IsSystemObject = false,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "InPrimaryKey",
|
||||
DisplayName = SR.FilterInPrimaryKey,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterInPrimaryKeyDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
currentChildren.Add(new FolderNode {
|
||||
NodeValue = SR.SchemaHierarchy_Triggers,
|
||||
@@ -2252,6 +2807,23 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
IsSystemObject = false,
|
||||
ValidFor = ValidForFlag.NotSqlDemand,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "IsMemoryOptimized",
|
||||
DisplayName = SR.FilterIsMemoryOptimized,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterIsMemoryOptimizedDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
currentChildren.Add(new FolderNode {
|
||||
NodeValue = SR.SchemaHierarchy_Statistics,
|
||||
@@ -2301,12 +2873,88 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
IsSystemObject = false,
|
||||
ValidFor = ValidForFlag.NotSqlDw,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Schema",
|
||||
DisplayName = SR.FilterSchema,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterSchemaDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "IsNativelyCompiled",
|
||||
DisplayName = SR.FilterIsNativelyCompiled,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterIsNativelyCompiledDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
currentChildren.Add(new FolderNode {
|
||||
NodeValue = SR.SchemaHierarchy_ScalarValuedFunctions,
|
||||
NodeTypeId = NodeTypes.ScalarValuedFunctions,
|
||||
IsSystemObject = false,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Schema",
|
||||
DisplayName = SR.FilterSchema,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterSchemaDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "IsNativelyCompiled",
|
||||
DisplayName = SR.FilterIsNativelyCompiled,
|
||||
Type = NodeFilterPropertyDataType.Boolean,
|
||||
Description = SR.FilterIsNativelyCompiledDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
currentChildren.Add(new FolderNode {
|
||||
NodeValue = SR.SchemaHierarchy_AggregateFunctions,
|
||||
@@ -2314,6 +2962,37 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
IsSystemObject = false,
|
||||
ValidFor = ValidForFlag.AllOnPrem|ValidForFlag.AzureV12,
|
||||
SortPriority = SmoTreeNode.NextSortPriority,
|
||||
FilterProperties = new NodeFilterProperty[]
|
||||
{
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Name",
|
||||
DisplayName = SR.FilterName,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterNameDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Schema",
|
||||
DisplayName = SR.FilterSchema,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterSchemaDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "Owner",
|
||||
DisplayName = SR.FilterOwner,
|
||||
Type = NodeFilterPropertyDataType.String,
|
||||
Description = SR.FilterOwnerDescription,
|
||||
},
|
||||
new NodeFilterProperty
|
||||
{
|
||||
Name = "CreateDate",
|
||||
DisplayName = SR.FilterCreateDate,
|
||||
Type = NodeFilterPropertyDataType.Date,
|
||||
Description = SR.FilterCreateDateDescription,
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,11 @@ using System.Collections.Generic;
|
||||
using System.Composition;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace;
|
||||
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
{
|
||||
|
||||
@@ -128,7 +130,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
|
||||
List<XmlElement> children = GetChildren(xmlFile, type);
|
||||
List<XmlElement> smoProperties = GetNodeSmoProperties(xmlFile, type);
|
||||
|
||||
// Load and parse Filters node
|
||||
// A <Filters> node is comprised of <Or> and <Filter> nodes
|
||||
// - A <Filter> node defines the properties to construct a NodePropertyFilter object
|
||||
@@ -299,6 +300,57 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
WriteLine(" ValidFor = {0},", GetValidForFlags(validFor));
|
||||
}
|
||||
WriteLine(" SortPriority = {0},", sortPriority);
|
||||
List<XmlElement> filterProperties = GetFilterProperties(xmlFile, childName);
|
||||
if(filterProperties.Count > 0)
|
||||
{
|
||||
WriteLine(" FilterProperties = new NodeFilterProperty[]");
|
||||
WriteLine(" {");
|
||||
foreach (var filterDef in filterProperties)
|
||||
{
|
||||
var filterName = filterDef.GetAttribute("Name");
|
||||
var filterDisplayName = filterDef.GetAttribute("LocLabel");
|
||||
var filterType = filterDef.GetAttribute("Type");
|
||||
var enumString = "NodeFilterPropertyDataType";
|
||||
switch (filterType)
|
||||
{
|
||||
case "string":
|
||||
enumString += ".String";
|
||||
break;
|
||||
case "bool":
|
||||
enumString += ".Boolean";
|
||||
break;
|
||||
case "date":
|
||||
enumString += ".Date";
|
||||
break;
|
||||
case "choice":
|
||||
enumString += ".Choice";
|
||||
break;
|
||||
}
|
||||
var filterDescription = filterDef.GetAttribute("Description");
|
||||
WriteLine(" new NodeFilterProperty");
|
||||
WriteLine(" {");
|
||||
WriteLine(" Name = \"{0}\",", filterName);
|
||||
WriteLine(" DisplayName = {0},", filterDisplayName);
|
||||
WriteLine(" Type = {0},", enumString);
|
||||
WriteLine(" Description = {0},", filterDescription);
|
||||
if(filterType == "choice")
|
||||
{
|
||||
var enumValues = filterDef.ChildNodes;
|
||||
WriteLine(" Choices = new string[] {");
|
||||
foreach (XmlElement enumValue in enumValues)
|
||||
{
|
||||
var enumValueName = enumValue.GetAttribute("Name");
|
||||
WriteLine(" \"{0}\",", enumValueName);
|
||||
|
||||
}
|
||||
WriteLine(" }");
|
||||
}
|
||||
WriteLine(" },");
|
||||
|
||||
}
|
||||
WriteLine(" }");
|
||||
}
|
||||
|
||||
WriteLine(" });");
|
||||
}
|
||||
|
||||
@@ -580,6 +632,33 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
|
||||
return retElements;
|
||||
}
|
||||
|
||||
|
||||
public static List<XmlElement> GetFilterProperties(string xmlFile, string nodeType)
|
||||
{
|
||||
XmlElement nodeElement = GetNodeElement(xmlFile, nodeType);
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load(xmlFile);
|
||||
|
||||
List<XmlElement> retElements = new List<XmlElement>();
|
||||
XmlNodeList nodeList = doc.SelectNodes(string.Format("/ServerExplorerTree/FilterProperties[@NodeName='{0}']/Property", nodeType));
|
||||
foreach (XmlNode item in nodeList)
|
||||
{
|
||||
var filterName = item.InnerText;
|
||||
XmlNodeList filterPropertyList = doc.SelectNodes(string.Format("/ServerExplorerTree/FilterProperty[@Name='{0}']", filterName));
|
||||
foreach (var filterProperty in filterPropertyList)
|
||||
{
|
||||
XmlElement itemAsElement = filterProperty as XmlElement;
|
||||
if (itemAsElement != null)
|
||||
{
|
||||
retElements.Add(itemAsElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
return retElements;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static List<XmlElement> GetNodeFilterValues(string xmlFile, string parentName, string filterProperty, bool orFilter = false)
|
||||
{
|
||||
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
|
||||
|
||||
@@ -565,4 +565,113 @@
|
||||
<ReverseDependencyList>
|
||||
<ReverseDependency Type="SqlUser" DependsOn="SqlRole;SqlRoleMembership"/>
|
||||
</ReverseDependencyList>
|
||||
|
||||
<FilterProperties NodeName="Databases">
|
||||
<Property>Name</Property>
|
||||
<Property>Owner</Property>
|
||||
<Property>CreateDate</Property>
|
||||
</FilterProperties>
|
||||
|
||||
<FilterProperties NodeName="Tables">
|
||||
<Property>Name</Property>
|
||||
<Property>Schema</Property>
|
||||
<Property>Owner</Property>
|
||||
<Property>DurabilityType</Property>
|
||||
<Property>IsMemoryOptimized</Property>
|
||||
<Property>CreateDate</Property>
|
||||
</FilterProperties>
|
||||
|
||||
<FilterProperties NodeName="SystemTables">
|
||||
<Property>Name</Property>
|
||||
<Property>Schema</Property>
|
||||
<Property>Owner</Property>
|
||||
<Property>DurabilityType</Property>
|
||||
<Property>IsMemoryOptimized</Property>
|
||||
<Property>CreateDate</Property>
|
||||
</FilterProperties>
|
||||
|
||||
<FilterProperties NodeName="DroppedLedgerTables">
|
||||
<Property>Name</Property>
|
||||
<Property>Schema</Property>
|
||||
<Property>Owner</Property>
|
||||
<Property>DurabilityType</Property>
|
||||
<Property>IsMemoryOptimized</Property>
|
||||
<Property>CreateDate</Property>
|
||||
</FilterProperties>
|
||||
|
||||
<FilterProperties NodeName="Views">
|
||||
<Property>Name</Property>
|
||||
<Property>Schema</Property>
|
||||
<Property>Owner</Property>
|
||||
<Property>CreateDate</Property>
|
||||
</FilterProperties>
|
||||
|
||||
<FilterProperties NodeName="DroppedLedgerViews">
|
||||
<Property>Name</Property>
|
||||
<Property>Schema</Property>
|
||||
<Property>Owner</Property>
|
||||
<Property>CreateDate</Property>
|
||||
</FilterProperties>
|
||||
|
||||
<FilterProperties NodeName="StoredProcedures">
|
||||
<Property>Name</Property>
|
||||
<Property>Schema</Property>
|
||||
<Property>Owner</Property>
|
||||
<Property>IsNativelyCompiled</Property>
|
||||
<Property>CreateDate</Property>
|
||||
</FilterProperties>
|
||||
|
||||
<FilterProperties NodeName="TableValuedFunctions">
|
||||
<Property>Name</Property>
|
||||
<Property>Schema</Property>
|
||||
<Property>Owner</Property>
|
||||
<Property>IsNativelyCompiled</Property>
|
||||
<Property>CreateDate</Property>
|
||||
</FilterProperties>
|
||||
|
||||
<FilterProperties NodeName="ScalarValuedFunctions">
|
||||
<Property>Name</Property>
|
||||
<Property>Schema</Property>
|
||||
<Property>Owner</Property>
|
||||
<Property>IsNativelyCompiled</Property>
|
||||
<Property>CreateDate</Property>
|
||||
</FilterProperties>
|
||||
|
||||
<FilterProperties NodeName="AggregateFunctions">
|
||||
<Property>Name</Property>
|
||||
<Property>Schema</Property>
|
||||
<Property>Owner</Property>
|
||||
<Property>CreateDate</Property>
|
||||
</FilterProperties>
|
||||
|
||||
<FilterProperties NodeName="Sequences">
|
||||
<Property>Name</Property>
|
||||
<Property>Schema</Property>
|
||||
<Property>Owner</Property>
|
||||
<Property>CreateDate</Property>
|
||||
</FilterProperties>
|
||||
|
||||
<FilterProperties NodeName="Indexes">
|
||||
<Property>Name</Property>
|
||||
<Property>IsMemoryOptimized</Property>
|
||||
</FilterProperties>
|
||||
|
||||
<FilterProperties NodeName="Columns">
|
||||
<Property>Name</Property>
|
||||
<Property>InPrimaryKey</Property>
|
||||
</FilterProperties>
|
||||
|
||||
|
||||
<FilterProperty Name="Name" LocLabel="SR.FilterName" Type="string" Description="SR.FilterNameDescription"/>
|
||||
<FilterProperty Name="Schema" LocLabel="SR.FilterSchema" Type="string" Description="SR.FilterSchemaDescription"/>
|
||||
<FilterProperty Name="Owner" LocLabel="SR.FilterOwner" Type="string" Description="SR.FilterOwnerDescription"/>
|
||||
<FilterProperty Name="DurabilityType" LocLabel="SR.FilterDurabilityType" Type="choice" Description="SR.FilterDurabilityTypeDescription">
|
||||
<Value Name="SchemaAndData" LocLabel="SR.SchemaAndData"/>
|
||||
<Value Name="SchemaOnly" LocLabel="SR.SchemaOnly"/>
|
||||
</FilterProperty>
|
||||
<FilterProperty Name="IsMemoryOptimized" LocLabel="SR.FilterIsMemoryOptimized" Type="bool" Description="SR.FilterIsMemoryOptimizedDescription"/>
|
||||
<FilterProperty Name="CreateDate" LocLabel="SR.FilterCreateDate" Type="date" Description="SR.FilterCreateDateDescription"/>
|
||||
<FilterProperty Name="IsNativelyCompiled" LocLabel="SR.FilterIsNativelyCompiled" Type="bool" Description="SR.FilterIsNativelyCompiledDescription"/>
|
||||
<FilterProperty Name="InPrimaryKey" LocLabel="SR.FilterInPrimaryKey" Type="bool" Description="SR.FilterInPrimaryKeyDescription"/>
|
||||
</ServerExplorerTree>
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
Property = "TemporalType",
|
||||
Type = typeof(Enum),
|
||||
TypeToReverse = typeof(SqlHistoryTableQuerier),
|
||||
ValidFor = ValidForFlag.Sql2016|ValidForFlag.Sql2017|ValidForFlag.Sql2019|ValidForFlag.Sql2022OrHigher|ValidForFlag.AzureV12,
|
||||
ValidFor = ValidForFlag.Sql2016 | ValidForFlag.Sql2017 | ValidForFlag.Sql2019 | ValidForFlag.Sql2022OrHigher | ValidForFlag.AzureV12,
|
||||
Values = new List<object>
|
||||
{
|
||||
{ TableTemporalType.HistoryTable }
|
||||
@@ -38,7 +38,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
Property = "LedgerType",
|
||||
Type = typeof(Enum),
|
||||
TypeToReverse = typeof(SqlHistoryTableQuerier),
|
||||
ValidFor = ValidForFlag.Sql2022OrHigher|ValidForFlag.AzureV12,
|
||||
ValidFor = ValidForFlag.Sql2022OrHigher | ValidForFlag.AzureV12,
|
||||
Values = new List<object>
|
||||
{
|
||||
{ LedgerTableType.HistoryTable }
|
||||
@@ -59,7 +59,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
[Test]
|
||||
public void NodeOrFilterReturnsProperString()
|
||||
{
|
||||
var orNode = new NodeOrFilter {
|
||||
var orNode = new NodeOrFilter
|
||||
{
|
||||
FilterList = new List<NodePropertyFilter> {
|
||||
TemporalFilter,
|
||||
LedgerHistoryFilter
|
||||
@@ -127,7 +128,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
[Test]
|
||||
public void GetPropertyFilterWithNodePropertyAndNodeOrFilters()
|
||||
{
|
||||
var orNode = new NodeOrFilter {
|
||||
var orNode = new NodeOrFilter
|
||||
{
|
||||
FilterList = new List<NodePropertyFilter> {
|
||||
TemporalFilter,
|
||||
LedgerHistoryFilter
|
||||
@@ -160,14 +162,16 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
public void GetPropertyFilterWithMixedFilters()
|
||||
{
|
||||
// All these filters together are nonsense, but it's just testing the logic for constructing the filter string
|
||||
var orNode = new NodeOrFilter {
|
||||
var orNode = new NodeOrFilter
|
||||
{
|
||||
FilterList = new List<NodePropertyFilter> {
|
||||
TemporalFilter,
|
||||
LedgerHistoryFilter
|
||||
}
|
||||
};
|
||||
|
||||
var orNode2 = new NodeOrFilter {
|
||||
var orNode2 = new NodeOrFilter
|
||||
{
|
||||
FilterList = new List<NodePropertyFilter> {
|
||||
SystemObjectFilter,
|
||||
LedgerHistoryFilter,
|
||||
@@ -218,5 +222,393 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
string expectedNewUrn = "[(@TemporalType = 1) and (@LedgerType = 1) and (@Schema = 'jsdafl983!@$#%535343]]]][[[')]";
|
||||
Assert.That(newUrn, Is.EqualTo(expectedNewUrn), "GetPropertyFilter did not construct the URN filter string as expected");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDateFilters()
|
||||
{
|
||||
// Testing date filter with equals
|
||||
var filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "CreateDate",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { "2021-01-01" },
|
||||
FilterType = FilterType.EQUALS,
|
||||
IsDateTime = true
|
||||
}
|
||||
};
|
||||
|
||||
string filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@CreateDate >= datetime('2021-01-01 00:00:00.000') and @CreateDate <= datetime('2021-01-01 23:59:59.999'))]", filterString, "Error parsing date filter with equals operator");
|
||||
|
||||
|
||||
// Testing date filter with less than
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "CreateDate",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { "2021-01-01" },
|
||||
FilterType = FilterType.LESSTHAN,
|
||||
IsDateTime = true
|
||||
}
|
||||
};
|
||||
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@CreateDate < datetime('2021-01-01 00:00:00.000'))]", filterString, "Error parsing date filter with less than operator");
|
||||
|
||||
// Testing date filter with greater than
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "CreateDate",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { "2021-01-01" },
|
||||
FilterType = FilterType.GREATERTHAN,
|
||||
IsDateTime = true
|
||||
}
|
||||
};
|
||||
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@CreateDate > datetime('2021-01-01 23:59:59.999'))]", filterString, "Error parsing date filter with greater than operator");
|
||||
|
||||
// Testing date filter with between
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "CreateDate",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { new string[] {"2021-01-01", "2021-01-02"}},
|
||||
FilterType = FilterType.BETWEEN,
|
||||
IsDateTime = true
|
||||
}
|
||||
};
|
||||
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@CreateDate >= datetime('2021-01-01 00:00:00.000') and @CreateDate <= datetime('2021-01-02 23:59:59.999'))]", filterString, "Error parsing date filter with between operator");
|
||||
|
||||
|
||||
// Testing date filter with not equals
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "CreateDate",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { "2021-01-01" },
|
||||
FilterType = FilterType.NOTEQUALS,
|
||||
IsDateTime = true,
|
||||
}
|
||||
};
|
||||
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(not(@CreateDate >= datetime('2021-01-01 00:00:00.000') and @CreateDate <= datetime('2021-01-01 23:59:59.999')))]", filterString, "Error parsing date filter with not equals operator");
|
||||
|
||||
// Testing date filter with not between
|
||||
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "CreateDate",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { new string[] {"2021-01-01", "2021-01-02"}},
|
||||
FilterType = FilterType.NOTBETWEEN,
|
||||
IsDateTime = true
|
||||
}
|
||||
};
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(not(@CreateDate >= datetime('2021-01-01 00:00:00.000') and @CreateDate <= datetime('2021-01-02 23:59:59.999')))]", filterString, "Error parsing date filter with not between operator");
|
||||
|
||||
// Testing date filter LessThanOrEquals
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "CreateDate",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { "2021-01-01" },
|
||||
FilterType = FilterType.LESSTHANOREQUAL,
|
||||
IsDateTime = true
|
||||
}
|
||||
};
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@CreateDate <= datetime('2021-01-01 23:59:59.999'))]", filterString, "Error parsing date filter with LessThanOrEquals operator");
|
||||
|
||||
// Testing date filter GreaterThanOrEquals
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "CreateDate",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { "2021-01-01" },
|
||||
FilterType = FilterType.GREATERTHANOREQUAL,
|
||||
IsDateTime = true
|
||||
}
|
||||
};
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@CreateDate >= datetime('2021-01-01 00:00:00.000'))]", filterString, "Error parsing date filter with GreaterThanOrEquals operator");
|
||||
|
||||
|
||||
// Testing date filter with invalid date
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "CreateDate",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { "invalid value" },
|
||||
FilterType = FilterType.EQUALS,
|
||||
IsDateTime = true
|
||||
}
|
||||
};
|
||||
Assert.Throws<FormatException>(() => INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All), "Error not thrown for creating a date sfc filter with invalid date");
|
||||
|
||||
// Testing date filter with invalid date for between operator
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "CreateDate",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { new string[] {"invalid value", "2021-01-02"}},
|
||||
FilterType = FilterType.BETWEEN,
|
||||
IsDateTime = true
|
||||
}
|
||||
};
|
||||
Assert.Throws<FormatException>(() => INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All), "Error not thrown when value array contains invalid date value for between operator");
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "CreateDate",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> {"2021-01-02"},
|
||||
FilterType = FilterType.BETWEEN,
|
||||
IsDateTime = true
|
||||
}
|
||||
};
|
||||
Assert.Throws<InvalidCastException>(() => INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All), "Error not thrown when only one date value is provided for between operator");
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "CreateDate",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { new string[] {"2021-01-02"}},
|
||||
FilterType = FilterType.BETWEEN,
|
||||
IsDateTime = true
|
||||
}
|
||||
};
|
||||
Assert.Throws<IndexOutOfRangeException>(() => INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All), "Error not thrown when only one value is provided in date array for between operator");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TextNumericFilters()
|
||||
{
|
||||
// Testing numeric filter with equals
|
||||
var filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "RowCount",
|
||||
Type = typeof(int),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { "100" },
|
||||
FilterType = FilterType.EQUALS,
|
||||
IsDateTime = false
|
||||
}
|
||||
};
|
||||
|
||||
string filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@RowCount = 100)]", filterString, "Error parsing numeric filter with equals operator");
|
||||
|
||||
// Testing numeric filter with less than
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "RowCount",
|
||||
Type = typeof(int),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { 100 },
|
||||
FilterType = FilterType.LESSTHAN,
|
||||
IsDateTime = false
|
||||
}
|
||||
};
|
||||
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@RowCount < 100)]", filterString, "Error parsing numeric filter with less than operator");
|
||||
|
||||
// Testing numeric filter with greater than
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "RowCount",
|
||||
Type = typeof(int),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { 100 },
|
||||
FilterType = FilterType.GREATERTHAN,
|
||||
IsDateTime = false
|
||||
}
|
||||
};
|
||||
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@RowCount > 100)]", filterString, "Error parsing numeric filter with greater than operator");
|
||||
|
||||
// Testing numeric filter with between
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "RowCount",
|
||||
Type = typeof(int),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { new object[] {100, 200}},
|
||||
FilterType = FilterType.BETWEEN,
|
||||
IsDateTime = false
|
||||
}
|
||||
};
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@RowCount >= 100 and @RowCount <= 200)]", filterString, "Error parsing numeric filter with between operator");
|
||||
|
||||
// Testing numeric filter with not equals
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "RowCount",
|
||||
Type = typeof(int),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { 100 },
|
||||
FilterType = FilterType.NOTEQUALS,
|
||||
IsDateTime = false,
|
||||
}
|
||||
};
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@RowCount != 100)]", filterString, "Error parsing numeric filter with not equals operator");
|
||||
|
||||
// Testing numeric filter with not between
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "RowCount",
|
||||
Type = typeof(int),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { new object[] {100, 200}},
|
||||
FilterType = FilterType.NOTBETWEEN,
|
||||
IsDateTime = false
|
||||
}
|
||||
};
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(not(@RowCount >= 100 and @RowCount <= 200))]", filterString, "Error parsing numeric filter with not between operator");
|
||||
|
||||
// Testing numeric filter LessThanOrEquals
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "RowCount",
|
||||
Type = typeof(int),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { 100 },
|
||||
FilterType = FilterType.LESSTHANOREQUAL,
|
||||
IsDateTime = false
|
||||
}
|
||||
};
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@RowCount <= 100)]", filterString, "Error parsing numeric filter with LessThanOrEquals operator");
|
||||
|
||||
// Testing numeric filter GreaterThanOrEquals
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "RowCount",
|
||||
Type = typeof(int),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { 100 },
|
||||
FilterType = FilterType.GREATERTHANOREQUAL,
|
||||
IsDateTime = false
|
||||
}
|
||||
};
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@RowCount >= 100)]", filterString, "Error parsing numeric filter with GreaterThanOrEquals operator");
|
||||
|
||||
// Testing numeric filter with invalid value
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "RowCount",
|
||||
Type = typeof(int),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { "invalid value" },
|
||||
FilterType = FilterType.EQUALS,
|
||||
IsDateTime = false
|
||||
}
|
||||
};
|
||||
Assert.Throws<FormatException>(() => INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All), "Error not thrown for creating a numeric sfc filter with invalid number");
|
||||
|
||||
// Testing numeric filter with invalid value for between operator
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "RowCount",
|
||||
Type = typeof(int),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { new object[] {"invalid value", 200}},
|
||||
FilterType = FilterType.BETWEEN,
|
||||
IsDateTime = false
|
||||
}
|
||||
};
|
||||
Assert.Throws<FormatException>(() => INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All), "Error not thrown for creating a numberic sfc filter with invalid array for between operator");
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "RowCount",
|
||||
Type = typeof(int),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> {200},
|
||||
FilterType = FilterType.BETWEEN,
|
||||
IsDateTime = false
|
||||
}
|
||||
};
|
||||
Assert.Throws<InvalidCastException>(() => INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All), "Error not thrown when a single value is passed for between operator");
|
||||
filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "RowCount",
|
||||
Type = typeof(int),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { new object[] {200}},
|
||||
FilterType = FilterType.BETWEEN,
|
||||
IsDateTime = false
|
||||
}
|
||||
};
|
||||
Assert.Throws<IndexOutOfRangeException>(() => INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All), "Error not thrown when the array contains single value for between operator");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@@ -297,7 +298,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
public void FindNodeCanExpandParentNodes()
|
||||
{
|
||||
var mockTreeNode = new Mock<TreeNode>();
|
||||
object[] populateChildrenArguments = { ItExpr.Is<bool>(x => x == false), ItExpr.IsNull<string>(), new CancellationToken(), ItExpr.IsNull<string>() };
|
||||
object[] populateChildrenArguments = { ItExpr.Is<bool>(x => x == false), ItExpr.IsNull<string>(), new CancellationToken(), ItExpr.IsNull<string>(), ItExpr.IsNull<IEnumerable<NodeFilter>>() };
|
||||
mockTreeNode.Protected().Setup("PopulateChildren", populateChildrenArguments);
|
||||
mockTreeNode.Object.IsAlwaysLeaf = false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user