Or Filtering on Object Explorer Nodes (#1608)

support for a more robust filtering system in the Object Explorer xml, allowing for or-ing filter properties together for use in URN querying for objects

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
This commit is contained in:
Jordan Hays
2022-07-29 18:35:37 -04:00
committed by GitHub
parent 40df024dbc
commit 3294a52ad9
10 changed files with 1229 additions and 827 deletions

View File

@@ -0,0 +1,195 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.Collections.Generic;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
using NUnit.Framework;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
{
public class NodeFilterTests
{
// Basic PropertyFilter definitions to use in tests
public NodePropertyFilter TemporalFilter =
new NodePropertyFilter
{
Property = "TemporalType",
Type = typeof(Enum),
TypeToReverse = typeof(SqlHistoryTableQuerier),
ValidFor = ValidForFlag.Sql2016|ValidForFlag.Sql2017|ValidForFlag.Sql2019|ValidForFlag.Sql2022|ValidForFlag.AzureV12,
Values = new List<object>
{
{ TableTemporalType.HistoryTable }
}
};
public NodePropertyFilter LedgerHistoryFilter =
new NodePropertyFilter
{
Property = "LedgerType",
Type = typeof(Enum),
TypeToReverse = typeof(SqlHistoryTableQuerier),
ValidFor = ValidForFlag.Sql2022|ValidForFlag.AzureV12,
Values = new List<object>
{
{ LedgerTableType.HistoryTable }
}
};
public NodePropertyFilter SystemObjectFilter =
new NodePropertyFilter
{
Property = "IsSystemObject",
Type = typeof(bool),
Values = new List<object> { 1 },
};
/// <summary>
/// Validates the output of the ToPropertyFilterString for the NodeOrFilter class
/// </summary>
[Test]
public void NodeOrFilterReturnsProperString()
{
var orNode = new NodeOrFilter {
FilterList = new List<NodePropertyFilter> {
TemporalFilter,
LedgerHistoryFilter
}
};
string allFiltersValid = orNode.ToPropertyFilterString(typeof(SqlHistoryTableQuerier), ValidForFlag.Sql2022);
string expectedAllFilters = "((@TemporalType = 1) or (@LedgerType = 1))";
Assert.That(allFiltersValid, Is.EqualTo(expectedAllFilters), "ToPropertyFilterString did not construct the URN filter string as expected for NodeOrFilter");
string sql2016ServerVersion = orNode.ToPropertyFilterString(typeof(SqlHistoryTableQuerier), ValidForFlag.Sql2016);
string expectedSql2016Filters = "((@TemporalType = 1))";
Assert.That(sql2016ServerVersion, Is.EqualTo(expectedSql2016Filters), "ToPropertyFilterString did not construct the URN filter string as expected when excluding filters that aren't valid for the given server type.");
string invalidQuerierType = orNode.ToPropertyFilterString(typeof(SqlTableQuerier), ValidForFlag.Sql2022);
Assert.That(invalidQuerierType, Is.Empty, "ToPropertyFilterString should return empty string, because no given filters match the querier type provided.");
}
/// <summary>
/// Validates the output of GetPropertyFilter with an NodeOrFilter
/// </summary>
[Test]
public void GetPropertyFilterWithNodeOrFilter()
{
var nodeList = new List<INodeFilter> {
new NodeOrFilter {
FilterList = new List<NodePropertyFilter> {
TemporalFilter,
LedgerHistoryFilter
}
}
};
string allFiltersValid = INodeFilter.GetPropertyFilter(nodeList, typeof(SqlHistoryTableQuerier), ValidForFlag.Sql2022);
string expectedAllFilters = "[((@TemporalType = 1) or (@LedgerType = 1))]";
Assert.That(allFiltersValid, Is.EqualTo(expectedAllFilters), "GetPropertyFilter did not construct the URN filter string as expected");
}
/// <summary>
/// Validates the output of GetPropertyFilter with a list of NodePropertyFilters
/// </summary>
[Test]
public void GetPropertyFilterWithNodePropertyFilters()
{
var nodeList = new List<INodeFilter> {
TemporalFilter,
LedgerHistoryFilter
};
string allFiltersValid = INodeFilter.GetPropertyFilter(nodeList, typeof(SqlHistoryTableQuerier), ValidForFlag.Sql2022);
string expectedAllFilters = "[(@TemporalType = 1) and (@LedgerType = 1)]";
Assert.That(allFiltersValid, Is.EqualTo(expectedAllFilters), "GetPropertyFilter did not construct the URN filter string as expected");
string sql2016ServerVersion = INodeFilter.GetPropertyFilter(nodeList, typeof(SqlHistoryTableQuerier), ValidForFlag.Sql2016);
string expectedSql2016Filters = "[(@TemporalType = 1)]";
Assert.That(sql2016ServerVersion, Is.EqualTo(expectedSql2016Filters), "GetPropertyFilter did not construct the URN filter string as expected when excluding filters that aren't valid for the given server type.");
string invalidQuerierType = INodeFilter.GetPropertyFilter(nodeList, typeof(SqlTableQuerier), ValidForFlag.Sql2022);
Assert.That(invalidQuerierType, Is.Empty, "GetPropertyFilter should return empty string, because no given filters match the querier type provided.");
}
/// <summary>
/// Validates the output of GetPropertyFilter with a list of both NodePropertyFilters and NodeOrFilters
/// </summary>
[Test]
public void GetPropertyFilterWithNodePropertyAndNodeOrFilters()
{
var orNode = new NodeOrFilter {
FilterList = new List<NodePropertyFilter> {
TemporalFilter,
LedgerHistoryFilter
}
};
var nodeList = new List<INodeFilter> {
orNode,
SystemObjectFilter
};
string allFiltersValid = INodeFilter.GetPropertyFilter(nodeList, typeof(SqlHistoryTableQuerier), ValidForFlag.Sql2022);
string expectedAllFilters = "[((@TemporalType = 1) or (@LedgerType = 1)) and (@IsSystemObject = 1)]";
Assert.That(allFiltersValid, Is.EqualTo(expectedAllFilters), "GetPropertyFilter did not construct the URN filter string as expected");
string sql2016ServerVersion = INodeFilter.GetPropertyFilter(nodeList, typeof(SqlHistoryTableQuerier), ValidForFlag.Sql2016);
string expectedSql2016Filters = "[((@TemporalType = 1)) and (@IsSystemObject = 1)]";
Assert.That(sql2016ServerVersion, Is.EqualTo(expectedSql2016Filters), "GetPropertyFilter did not construct the URN filter string as expected when excluding filters that aren't valid for the given server type.");
string invalidQuerierType = INodeFilter.GetPropertyFilter(nodeList, typeof(SqlTableQuerier), ValidForFlag.Sql2022);
string expectedTableQuerierFilters = "[(@IsSystemObject = 1)]";
Assert.That(invalidQuerierType, Is.EqualTo(expectedTableQuerierFilters), "GetPropertyFilter did not construct the URN filter string as expected when excluding filters that don't match the querier type.");
}
/// <summary>
/// Validates the output of GetPropertyFilter with a list of multiple NodeOrFilters with more than 2 filters, and
/// a lone NodePropertyFilter
/// </summary>
[Test]
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 {
FilterList = new List<NodePropertyFilter> {
TemporalFilter,
LedgerHistoryFilter
}
};
var orNode2 = new NodeOrFilter {
FilterList = new List<NodePropertyFilter> {
SystemObjectFilter,
LedgerHistoryFilter,
TemporalFilter
}
};
var nodeList = new List<INodeFilter> {
orNode,
SystemObjectFilter,
orNode2
};
string allFiltersValid = INodeFilter.GetPropertyFilter(nodeList, typeof(SqlHistoryTableQuerier), ValidForFlag.Sql2022);
string expectedAllFilters = "[((@TemporalType = 1) or (@LedgerType = 1)) and (@IsSystemObject = 1) and ((@IsSystemObject = 1) or (@LedgerType = 1) or (@TemporalType = 1))]";
Assert.That(allFiltersValid, Is.EqualTo(expectedAllFilters), "GetPropertyFilter did not construct the URN filter string as expected");
string sql2016ServerVersion = INodeFilter.GetPropertyFilter(nodeList, typeof(SqlHistoryTableQuerier), ValidForFlag.Sql2016);
string expectedSql2016Filters = "[((@TemporalType = 1)) and (@IsSystemObject = 1) and ((@IsSystemObject = 1) or (@TemporalType = 1))]";
Assert.That(sql2016ServerVersion, Is.EqualTo(expectedSql2016Filters), "GetPropertyFilter did not construct the URN filter string as expected when excluding filters that aren't valid for the given server type.");
string invalidQuerierType = INodeFilter.GetPropertyFilter(nodeList, typeof(SqlTableQuerier), ValidForFlag.Sql2022);
string expectedTableQuerierFilters = "[(@IsSystemObject = 1) and ((@IsSystemObject = 1))]";
Assert.That(invalidQuerierType, Is.EqualTo(expectedTableQuerierFilters), "GetPropertyFilter did not construct the URN filter string as expected when excluding filters that don't match the querier type.");
}
}
}

View File

@@ -9,6 +9,7 @@ using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using NUnit.Framework;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
@@ -77,7 +78,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
var tableFactory = new TableValuedFunctionsChildFactory();
var filters = tableFactory.Filters;
Assert.True(filters.ToList().Any(filter => {
return filter.Values.Contains(UserDefinedFunctionType.Table) && filter.Values.Contains(UserDefinedFunctionType.Inline);
var f = filter as NodePropertyFilter;
return f.Values.Contains(UserDefinedFunctionType.Table) && f.Values.Contains(UserDefinedFunctionType.Inline);
}));
}