mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
Adding like filter and removing contains to OE filtering (#2105)
* Adding startswith and like filter * Adding ends with * Adding tests * Remove null and not null * Fixing string * Update test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/NodeFilterTests.cs Co-authored-by: Charles Gagnon <chgagnon@microsoft.com> * Update test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/NodeFilterTests.cs Co-authored-by: Charles Gagnon <chgagnon@microsoft.com> * Adding back contains, starts with and ends with * Properly escaping chars for like based filters * Adding some comments regarding escape characters * Using generated regex * removing additional class * Adding extra auth type that was causing the tests to error out * Fixing regex * Adding integration tests * Fixing unit tests * Making fluent assertions --------- Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
This commit is contained in:
@@ -157,6 +157,10 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts
|
||||
NotBetween = 7,
|
||||
Contains = 8,
|
||||
NotContains = 9,
|
||||
StartsWith = 10,
|
||||
NotStartsWith = 11,
|
||||
EndsWith = 12,
|
||||
NotEndsWith = 13
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -8,13 +8,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.SqlTools.ServiceLayer.Management;
|
||||
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
{
|
||||
/// <summary>
|
||||
/// Has information for filtering a SMO object by properties
|
||||
/// </summary>
|
||||
public class NodePropertyFilter : INodeFilter
|
||||
public partial class NodePropertyFilter : INodeFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Property name
|
||||
@@ -182,7 +185,25 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
object propertyValue = value;
|
||||
if (Type == typeof(string))
|
||||
{
|
||||
propertyValue = $"'{propertyValue}'";
|
||||
//Replacing quotes with double quotes
|
||||
var escapedString = CUtils.EscapeStringSQuote(propertyValue.ToString());
|
||||
if (this.FilterType == FilterType.STARTSWITH || this.FilterType == FilterType.ENDSWITH)
|
||||
{
|
||||
escapedString = EscapeLikeURNRegex().Replace(escapedString, "[$0]");
|
||||
|
||||
if (this.FilterType == FilterType.STARTSWITH)
|
||||
{
|
||||
propertyValue = $"'{escapedString}%'";
|
||||
}
|
||||
else if (this.FilterType == FilterType.ENDSWITH)
|
||||
{
|
||||
propertyValue = $"'%{escapedString}'";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
propertyValue = $"'{escapedString}'";
|
||||
}
|
||||
}
|
||||
else if (Type == typeof(Enum))
|
||||
{
|
||||
@@ -211,15 +232,19 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
case FilterType.DATETIME:
|
||||
filterText = $"@{Property} = datetime({propertyValue})";
|
||||
break;
|
||||
case FilterType.CONTAINS:
|
||||
filterText = $"contains(@{Property}, {propertyValue})";
|
||||
break;
|
||||
case FilterType.FALSE:
|
||||
filterText = $"@{Property} = false()";
|
||||
break;
|
||||
case FilterType.ISNULL:
|
||||
filterText = $"isnull(@{Property})";
|
||||
break;
|
||||
case FilterType.CONTAINS:
|
||||
filterText = $"contains(@{Property}, {propertyValue})";
|
||||
break;
|
||||
case FilterType.STARTSWITH:
|
||||
case FilterType.ENDSWITH:
|
||||
filterText = $"like(@{Property}, {propertyValue})";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,13 +286,17 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// For filters that use the LIKE operator, we need to escape the following characters: %, _, [, ^
|
||||
// we do this by wrapping them in square brackets eg: [%], [_], [[], [^]
|
||||
[GeneratedRegexAttribute(@"%|_|\[|\^")]
|
||||
public static partial Regex EscapeLikeURNRegex();
|
||||
}
|
||||
|
||||
public enum FilterType
|
||||
{
|
||||
EQUALS,
|
||||
DATETIME,
|
||||
CONTAINS,
|
||||
FALSE,
|
||||
ISNULL,
|
||||
NOTEQUALS,
|
||||
@@ -276,6 +305,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
|
||||
LESSTHANOREQUAL,
|
||||
GREATERTHANOREQUAL,
|
||||
BETWEEN,
|
||||
NOTBETWEEN
|
||||
NOTBETWEEN,
|
||||
CONTAINS,
|
||||
STARTSWITH,
|
||||
ENDSWITH
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,13 +129,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
|
||||
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;
|
||||
@@ -143,9 +136,29 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
|
||||
filterType = FilterType.NOTBETWEEN;
|
||||
isNotFilter = true;
|
||||
break;
|
||||
case NodeFilterOperator.Contains:
|
||||
filterType = FilterType.CONTAINS;
|
||||
break;
|
||||
case NodeFilterOperator.NotContains:
|
||||
filterType = FilterType.CONTAINS;
|
||||
isNotFilter = true;
|
||||
break;
|
||||
case NodeFilterOperator.StartsWith:
|
||||
filterType = FilterType.STARTSWITH;
|
||||
break;
|
||||
case NodeFilterOperator.NotStartsWith:
|
||||
filterType = FilterType.STARTSWITH;
|
||||
isNotFilter = true;
|
||||
break;
|
||||
case NodeFilterOperator.EndsWith:
|
||||
filterType = FilterType.ENDSWITH;
|
||||
break;
|
||||
case NodeFilterOperator.NotEndsWith:
|
||||
filterType = FilterType.ENDSWITH;
|
||||
isNotFilter = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (filter.Operator == NodeFilterOperator.Between || filter.Operator == NodeFilterOperator.NotBetween)
|
||||
{
|
||||
if (filterProperty.Type == NodeFilterPropertyDataType.Number)
|
||||
|
||||
@@ -279,13 +279,13 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
|
||||
"db_owner",
|
||||
"db_securityadmin"
|
||||
};
|
||||
foreach(var nodes in databaseChildren.Nodes)
|
||||
foreach (var nodes in databaseChildren.Nodes)
|
||||
{
|
||||
Assert.That(legacySchemas, Does.Not.Contain(nodes.Label), "Legacy schema node should not be found in database node when group by schema is enabled");
|
||||
}
|
||||
var legacySchemasNode = databaseChildren.Nodes.First(t => t.Label == SR.SchemaHierarchy_BuiltInSchema);
|
||||
var legacySchemasChildren = await _service.ExpandNode(session, legacySchemasNode.NodePath);
|
||||
foreach(var nodes in legacySchemasChildren.Nodes)
|
||||
foreach (var nodes in legacySchemasChildren.Nodes)
|
||||
{
|
||||
Assert.That(legacySchemas, Does.Contain(nodes.Label), "Legacy schema nodes should be found in legacy schemas folder when group by schema is enabled");
|
||||
}
|
||||
@@ -293,6 +293,95 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task VerifyOEFilters()
|
||||
{
|
||||
string query = @"
|
||||
Create table ""table['^__']"" (id int);
|
||||
Create table ""table['^__']2"" (id int);
|
||||
Create table ""table['^%%2"" (id int);
|
||||
Create table ""testTable"" (id int);
|
||||
";
|
||||
|
||||
string databaseName = "#testDb#";
|
||||
await RunTest(databaseName, query, "Testdb", async (testDbName, session) =>
|
||||
{
|
||||
var databaseNode = session.Root.ToNodeInfo();
|
||||
var databaseChildren = await _service.ExpandNode(session, databaseNode.NodePath);
|
||||
Assert.True(databaseChildren.Nodes.Any(t => t.Label == SR.SchemaHierarchy_Tables), "Tables node should be found in database node");
|
||||
var tablesNode = databaseChildren.Nodes.First(t => t.Label == SR.SchemaHierarchy_Tables);
|
||||
var NameProperty = tablesNode.FilterableProperties.First(t => t.Name == "Name");
|
||||
Assert.True(NameProperty != null, "Name property should be found in tables node");
|
||||
|
||||
// Testing contains operator
|
||||
NodeFilter filter = new NodeFilter()
|
||||
{
|
||||
Name = NameProperty.Name,
|
||||
Value = "table",
|
||||
Operator = NodeFilterOperator.Contains
|
||||
};
|
||||
var tablesChildren = await _service.ExpandNode(session, tablesNode.NodePath, true, null, new NodeFilter[] { filter });
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.testTable"), "testTable node should be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^__']"), "table['^__'] node should be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^__']2"), "table['^__']2 node should be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^%%2"), "table['^%%2 node should be found in tables node");
|
||||
|
||||
// Testing starts with operator
|
||||
filter = new NodeFilter()
|
||||
{
|
||||
Name = NameProperty.Name,
|
||||
Value = "table['^__']",
|
||||
Operator = NodeFilterOperator.StartsWith
|
||||
};
|
||||
tablesChildren = await _service.ExpandNode(session, tablesNode.NodePath, true, null, new NodeFilter[] { filter });
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^__']"), "table['^__'] node should be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^__']2"), "table['^__']2 node should be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.testTable") == false, "testTable node should not be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^%%2") == false, "table['^%%2 node should not be found in tables node");
|
||||
|
||||
// Testing starts with operator
|
||||
filter = new NodeFilter()
|
||||
{
|
||||
Name = NameProperty.Name,
|
||||
Value = "table['^%%2",
|
||||
Operator = NodeFilterOperator.StartsWith
|
||||
};
|
||||
tablesChildren = await _service.ExpandNode(session, tablesNode.NodePath, true, null, new NodeFilter[] { filter });
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^%%2"), "table['^%%2 node should be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^__']") == false, "table['^__'] node should not be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^__']2") == false, "table['^__']2 node should not be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.testTable") == false, "testTable node should not be found in tables node");
|
||||
|
||||
|
||||
// Testing ends with operator
|
||||
filter = new NodeFilter()
|
||||
{
|
||||
Name = NameProperty.Name,
|
||||
Value = "table['^__']",
|
||||
Operator = NodeFilterOperator.EndsWith
|
||||
};
|
||||
tablesChildren = await _service.ExpandNode(session, tablesNode.NodePath, true, null, new NodeFilter[] { filter });
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^__']"), "table['^__'] node should be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^__']2") == false, "table['^__']2 node should not be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.testTable") == false, "testTable node should not be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^%%2") == false, "table['^%%2 node should not be found in tables node");
|
||||
|
||||
// Testing equals operator
|
||||
filter = new NodeFilter()
|
||||
{
|
||||
Name = NameProperty.Name,
|
||||
Value = "table['^__']",
|
||||
Operator = NodeFilterOperator.Equals
|
||||
};
|
||||
tablesChildren = await _service.ExpandNode(session, tablesNode.NodePath, true, null, new NodeFilter[] { filter });
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^__']"), "table['^__'] node should be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^__']2") == false, "table['^__']2 node should not be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.testTable") == false, "testTable node should not be found in tables node");
|
||||
Assert.That(tablesChildren.Nodes.Any(t => t.Label == "dbo.table['^%%2") == false, "table['^%%2 node should not be found in tables node");
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private async Task VerifyRefresh(ObjectExplorerSession session, string tablePath, string tableName, bool deleted = true)
|
||||
{
|
||||
//Refresh Root
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
|
||||
public enum AuthenticationType
|
||||
{
|
||||
Integrated,
|
||||
SqlLogin
|
||||
SqlLogin,
|
||||
AzureMFA
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,14 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
|
||||
using NUnit.Framework;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
{
|
||||
@@ -241,7 +244,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
};
|
||||
|
||||
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");
|
||||
Assert.That(filterString, Is.EqualTo("[(@CreateDate >= datetime('2021-01-01 00:00:00.000') and @CreateDate <= datetime('2021-01-01 23:59:59.999'))]"), "Error parsing date filter with equals operator");
|
||||
|
||||
|
||||
// Testing date filter with less than
|
||||
@@ -259,7 +262,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
};
|
||||
|
||||
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");
|
||||
Assert.That(filterString, Is.EqualTo("[(@CreateDate < datetime('2021-01-01 00:00:00.000'))]"), "Error parsing date filter with less than operator");
|
||||
|
||||
// Testing date filter with greater than
|
||||
filterList = new List<NodePropertyFilter>
|
||||
@@ -276,7 +279,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
};
|
||||
|
||||
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");
|
||||
Assert.That(filterString, Is.EqualTo("[(@CreateDate > datetime('2021-01-01 23:59:59.999'))]"), "Error parsing date filter with greater than operator");
|
||||
|
||||
// Testing date filter with between
|
||||
filterList = new List<NodePropertyFilter>
|
||||
@@ -293,7 +296,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
};
|
||||
|
||||
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");
|
||||
Assert.That(filterString, Is.EqualTo("[(@CreateDate >= datetime('2021-01-01 00:00:00.000') and @CreateDate <= datetime('2021-01-02 23:59:59.999'))]"), "Error parsing date filter with between operator");
|
||||
|
||||
|
||||
// Testing date filter with not equals
|
||||
@@ -311,7 +314,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
};
|
||||
|
||||
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");
|
||||
Assert.That(filterString, Is.EqualTo("[(not(@CreateDate >= datetime('2021-01-01 00:00:00.000') and @CreateDate <= datetime('2021-01-01 23:59:59.999')))]"), "Error parsing date filter with not equals operator");
|
||||
|
||||
// Testing date filter with not between
|
||||
|
||||
@@ -328,7 +331,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
}
|
||||
};
|
||||
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");
|
||||
Assert.That(filterString, Is.EqualTo("[(not(@CreateDate >= datetime('2021-01-01 00:00:00.000') and @CreateDate <= datetime('2021-01-02 23:59:59.999')))]"), "Error parsing date filter with not between operator");
|
||||
|
||||
// Testing date filter LessThanOrEquals
|
||||
filterList = new List<NodePropertyFilter>
|
||||
@@ -344,7 +347,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
}
|
||||
};
|
||||
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");
|
||||
Assert.That(filterString, Is.EqualTo("[(@CreateDate <= datetime('2021-01-01 23:59:59.999'))]"), "Error parsing date filter with LessThanOrEquals operator");
|
||||
|
||||
// Testing date filter GreaterThanOrEquals
|
||||
filterList = new List<NodePropertyFilter>
|
||||
@@ -360,7 +363,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
}
|
||||
};
|
||||
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");
|
||||
Assert.That(filterString, Is.EqualTo("[(@CreateDate >= datetime('2021-01-01 00:00:00.000'))]"), "Error parsing date filter with GreaterThanOrEquals operator");
|
||||
|
||||
|
||||
// Testing date filter with invalid date
|
||||
@@ -438,7 +441,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
};
|
||||
|
||||
string filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@RowCount = 100)]", filterString, "Error parsing numeric filter with equals operator");
|
||||
Assert.That(filterString, Is.EqualTo("[(@RowCount = 100)]"), "Error parsing numeric filter with equals operator");
|
||||
|
||||
// Testing numeric filter with less than
|
||||
filterList = new List<NodePropertyFilter>
|
||||
@@ -455,7 +458,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
};
|
||||
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@RowCount < 100)]", filterString, "Error parsing numeric filter with less than operator");
|
||||
Assert.That(filterString, Is.EqualTo("[(@RowCount < 100)]"), "Error parsing numeric filter with less than operator");
|
||||
|
||||
// Testing numeric filter with greater than
|
||||
filterList = new List<NodePropertyFilter>
|
||||
@@ -472,7 +475,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
};
|
||||
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@RowCount > 100)]", filterString, "Error parsing numeric filter with greater than operator");
|
||||
Assert.That(filterString, Is.EqualTo("[(@RowCount > 100)]"), "Error parsing numeric filter with greater than operator");
|
||||
|
||||
// Testing numeric filter with between
|
||||
filterList = new List<NodePropertyFilter>
|
||||
@@ -488,7 +491,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
}
|
||||
};
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@RowCount >= 100 and @RowCount <= 200)]", filterString, "Error parsing numeric filter with between operator");
|
||||
Assert.That(filterString, Is.EqualTo("[(@RowCount >= 100 and @RowCount <= 200)]"), "Error parsing numeric filter with between operator");
|
||||
|
||||
// Testing numeric filter with not equals
|
||||
filterList = new List<NodePropertyFilter>
|
||||
@@ -504,7 +507,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
}
|
||||
};
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@RowCount != 100)]", filterString, "Error parsing numeric filter with not equals operator");
|
||||
Assert.That(filterString, Is.EqualTo("[(@RowCount != 100)]"), "Error parsing numeric filter with not equals operator");
|
||||
|
||||
// Testing numeric filter with not between
|
||||
filterList = new List<NodePropertyFilter>
|
||||
@@ -520,7 +523,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
}
|
||||
};
|
||||
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");
|
||||
Assert.That(filterString, Is.EqualTo("[(not(@RowCount >= 100 and @RowCount <= 200))]"), "Error parsing numeric filter with not between operator");
|
||||
|
||||
// Testing numeric filter LessThanOrEquals
|
||||
filterList = new List<NodePropertyFilter>
|
||||
@@ -536,7 +539,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
}
|
||||
};
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@RowCount <= 100)]", filterString, "Error parsing numeric filter with LessThanOrEquals operator");
|
||||
Assert.That(filterString, Is.EqualTo("[(@RowCount <= 100)]"), "Error parsing numeric filter with LessThanOrEquals operator");
|
||||
|
||||
// Testing numeric filter GreaterThanOrEquals
|
||||
filterList = new List<NodePropertyFilter>
|
||||
@@ -552,7 +555,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
}
|
||||
};
|
||||
filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.AreEqual("[(@RowCount >= 100)]", filterString, "Error parsing numeric filter with GreaterThanOrEquals operator");
|
||||
Assert.That(filterString, Is.EqualTo("[(@RowCount >= 100)]"), filterString, "Error parsing numeric filter with GreaterThanOrEquals operator");
|
||||
|
||||
// Testing numeric filter with invalid value
|
||||
filterList = new List<NodePropertyFilter>
|
||||
@@ -610,5 +613,352 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
|
||||
};
|
||||
Assert.Throws<IndexOutOfRangeException>(() => INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All), "Error not thrown when the array contains single value for between operator");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestContainsFilter()
|
||||
{
|
||||
// Testing text filter with ends with operator
|
||||
var filterList = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "Name",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { "test" },
|
||||
FilterType = FilterType.CONTAINS,
|
||||
IsDateTime = false
|
||||
}
|
||||
};
|
||||
var filterString = INodeFilter.GetPropertyFilter(filterList, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.That(filterString, Is.EqualTo("[(contains(@Name, 'test'))]"), "Error parsing text filter with contains operator");
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> ConvertExpandNodeFilterToNodeFilterTestCases
|
||||
{
|
||||
get
|
||||
{
|
||||
// Test case for equals operator
|
||||
yield return new TestCaseData(
|
||||
new NodeFilter()
|
||||
{
|
||||
Name = "Name",
|
||||
Operator = NodeFilterOperator.Equals,
|
||||
Value = "test"
|
||||
},
|
||||
new NodeFilterProperty()
|
||||
{
|
||||
Name = "Name",
|
||||
Type = NodeFilterPropertyDataType.String
|
||||
},
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "Name",
|
||||
Type = typeof(string),
|
||||
Values = new List<object> { "test" },
|
||||
IsNotFilter = false,
|
||||
FilterType = FilterType.EQUALS,
|
||||
IsDateTime = false
|
||||
}
|
||||
);
|
||||
|
||||
// Test case for not equals operator
|
||||
yield return new TestCaseData(
|
||||
new NodeFilter()
|
||||
{
|
||||
Name = "Name",
|
||||
Operator = NodeFilterOperator.NotEquals,
|
||||
Value = "test"
|
||||
},
|
||||
new NodeFilterProperty()
|
||||
{
|
||||
Name = "Name",
|
||||
Type = NodeFilterPropertyDataType.String
|
||||
},
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "Name",
|
||||
Type = typeof(string),
|
||||
Values = new List<object> { "test" },
|
||||
IsNotFilter = true,
|
||||
FilterType = FilterType.EQUALS,
|
||||
IsDateTime = false
|
||||
}
|
||||
);
|
||||
|
||||
// Test case for like operator with string value
|
||||
yield return new TestCaseData(
|
||||
new NodeFilter()
|
||||
{
|
||||
Name = "Name",
|
||||
Operator = NodeFilterOperator.Contains,
|
||||
Value = "test"
|
||||
},
|
||||
new NodeFilterProperty()
|
||||
{
|
||||
Name = "Name",
|
||||
Type = NodeFilterPropertyDataType.String
|
||||
},
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "Name",
|
||||
Type = typeof(string),
|
||||
Values = new List<object> { "test" },
|
||||
IsNotFilter = false,
|
||||
FilterType = FilterType.CONTAINS,
|
||||
IsDateTime = false
|
||||
}
|
||||
);
|
||||
|
||||
// Test case for not like operator with string value
|
||||
yield return new TestCaseData(
|
||||
new NodeFilter()
|
||||
{
|
||||
Name = "Name",
|
||||
Operator = NodeFilterOperator.NotContains,
|
||||
Value = "test"
|
||||
},
|
||||
new NodeFilterProperty()
|
||||
{
|
||||
Name = "Name",
|
||||
Type = NodeFilterPropertyDataType.String
|
||||
},
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "Name",
|
||||
Type = typeof(string),
|
||||
Values = new List<object> { "test" },
|
||||
IsNotFilter = true,
|
||||
FilterType = FilterType.CONTAINS,
|
||||
IsDateTime = false
|
||||
}
|
||||
);
|
||||
|
||||
// Test case for date filter with equals operator
|
||||
yield return new TestCaseData(
|
||||
new NodeFilter()
|
||||
{
|
||||
Name = "Date",
|
||||
Operator = NodeFilterOperator.Equals,
|
||||
Value = "2020-01-01"
|
||||
},
|
||||
new NodeFilterProperty()
|
||||
{
|
||||
Name = "Date",
|
||||
Type = NodeFilterPropertyDataType.Date
|
||||
},
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "Date",
|
||||
Type = typeof(string),
|
||||
Values = new List<object> { "2020-01-01" },
|
||||
IsNotFilter = false,
|
||||
FilterType = FilterType.EQUALS,
|
||||
IsDateTime = true
|
||||
}
|
||||
);
|
||||
|
||||
// test case for date with between operator
|
||||
yield return new TestCaseData(
|
||||
new NodeFilter()
|
||||
{
|
||||
Name = "Date",
|
||||
Operator = NodeFilterOperator.Between,
|
||||
Value = JArray.FromObject(new string[] { "2020-01-01", "2020-01-02" })
|
||||
},
|
||||
new NodeFilterProperty()
|
||||
{
|
||||
Name = "Date",
|
||||
Type = NodeFilterPropertyDataType.Date
|
||||
},
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "Date",
|
||||
Type = typeof(string),
|
||||
Values = new List<object> { new string[] { "2020-01-01", "2020-01-02" } },
|
||||
IsNotFilter = false,
|
||||
FilterType = FilterType.BETWEEN,
|
||||
IsDateTime = true
|
||||
}
|
||||
);
|
||||
|
||||
// test case for date with not between operator
|
||||
yield return new TestCaseData(
|
||||
new NodeFilter()
|
||||
{
|
||||
Name = "Date",
|
||||
Operator = NodeFilterOperator.NotBetween,
|
||||
Value = JArray.FromObject(new string[] { "2020-01-01", "2020-01-02" })
|
||||
},
|
||||
new NodeFilterProperty()
|
||||
{
|
||||
Name = "Date",
|
||||
Type = NodeFilterPropertyDataType.Date
|
||||
},
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "Date",
|
||||
Type = typeof(string),
|
||||
Values = new List<object> { new string[] { "2020-01-01", "2020-01-02" } },
|
||||
IsNotFilter = true,
|
||||
FilterType = FilterType.NOTBETWEEN,
|
||||
IsDateTime = true
|
||||
}
|
||||
);
|
||||
|
||||
// test case for date with starts with operator
|
||||
yield return new TestCaseData(
|
||||
new NodeFilter()
|
||||
{
|
||||
Name = "Name",
|
||||
Operator = NodeFilterOperator.StartsWith,
|
||||
Value = "test"
|
||||
},
|
||||
new NodeFilterProperty()
|
||||
{
|
||||
Name = "Name",
|
||||
Type = NodeFilterPropertyDataType.String
|
||||
},
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "Name",
|
||||
Type = typeof(string),
|
||||
Values = new List<object> { "test" },
|
||||
IsNotFilter = false,
|
||||
FilterType = FilterType.STARTSWITH,
|
||||
IsDateTime = false
|
||||
}
|
||||
);
|
||||
|
||||
// test case for date with not starts with operator
|
||||
yield return new TestCaseData(
|
||||
new NodeFilter()
|
||||
{
|
||||
Name = "Name",
|
||||
Operator = NodeFilterOperator.NotStartsWith,
|
||||
Value = "test"
|
||||
},
|
||||
new NodeFilterProperty()
|
||||
{
|
||||
Name = "Name",
|
||||
Type = NodeFilterPropertyDataType.String
|
||||
},
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "Name",
|
||||
Type = typeof(string),
|
||||
Values = new List<object> { "test" },
|
||||
IsNotFilter = true,
|
||||
FilterType = FilterType.STARTSWITH,
|
||||
IsDateTime = false
|
||||
}
|
||||
);
|
||||
|
||||
// test case for date with ends with operator
|
||||
yield return new TestCaseData(
|
||||
new NodeFilter()
|
||||
{
|
||||
Name = "Name",
|
||||
Operator = NodeFilterOperator.EndsWith,
|
||||
Value = "test"
|
||||
},
|
||||
new NodeFilterProperty()
|
||||
{
|
||||
Name = "Name",
|
||||
Type = NodeFilterPropertyDataType.String
|
||||
},
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "Name",
|
||||
Type = typeof(string),
|
||||
Values = new List<object> { "test" },
|
||||
IsNotFilter = false,
|
||||
FilterType = FilterType.ENDSWITH,
|
||||
IsDateTime = false
|
||||
}
|
||||
);
|
||||
|
||||
// test case for date with not ends with operator
|
||||
yield return new TestCaseData(
|
||||
new NodeFilter()
|
||||
{
|
||||
Name = "Name",
|
||||
Operator = NodeFilterOperator.NotEndsWith,
|
||||
Value = "test"
|
||||
},
|
||||
new NodeFilterProperty()
|
||||
{
|
||||
Name = "Name",
|
||||
Type = NodeFilterPropertyDataType.String
|
||||
},
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "Name",
|
||||
Type = typeof(string),
|
||||
Values = new List<object> { "test" },
|
||||
IsNotFilter = true,
|
||||
FilterType = FilterType.ENDSWITH,
|
||||
IsDateTime = false
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource("ConvertExpandNodeFilterToNodeFilterTestCases")]
|
||||
public void TestConvertExpandNodeFilterToNodeFilter(NodeFilter filter, NodeFilterProperty prop, INodeFilter expectedParsedFilter)
|
||||
{
|
||||
INodeFilter actualParsedFilter = ObjectExplorerUtils.ConvertExpandNodeFilterToNodeFilter(filter, prop);
|
||||
Assert.That(
|
||||
JsonConvert.SerializeObject(actualParsedFilter),
|
||||
Is.EqualTo(JsonConvert.SerializeObject(expectedParsedFilter)),
|
||||
$"Error parsing node filter '{prop.Name} ({prop.Type.ToString()})' with operator '{filter.Operator.ToString()}' and value '{filter.Value}'"
|
||||
);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("test''test", "[(@Name = 'test''''test')]", "[(like(@Name, 'test''''test%'))]")]
|
||||
[TestCase("test'test", "[(@Name = 'test''test')]", "[(like(@Name, 'test''test%'))]")]
|
||||
[TestCase("test'test'test", "[(@Name = 'test''test''test')]", "[(like(@Name, 'test''test''test%'))]")]
|
||||
[TestCase("test'[test]test", "[(@Name = 'test''[test]test')]", "[(like(@Name, 'test''[[]test]test%'))]")]
|
||||
[TestCase("test^][%test", "[(@Name = 'test^][%test')]", "[(like(@Name, 'test[^]][[][%]test%'))]")]
|
||||
[TestCase("test%test", "[(@Name = 'test%test')]", "[(like(@Name, 'test[%]test%'))]")]
|
||||
[TestCase("test[test", "[(@Name = 'test[test')]", "[(like(@Name, 'test[[]test%'))]")]
|
||||
[TestCase("test]test", "[(@Name = 'test]test')]", "[(like(@Name, 'test]test%'))]")]
|
||||
[TestCase("test%%'%%test", "[(@Name = 'test%%''%%test')]", "[(like(@Name, 'test[%][%]''[%][%]test%'))]")]
|
||||
public void TestFilterValuesWithSpecialCharacters(string input, string expectedFilterValue, string expectedLikeFilterValue)
|
||||
{
|
||||
var nonLikeFilter = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "Name",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { input },
|
||||
FilterType = FilterType.EQUALS,
|
||||
IsDateTime = false
|
||||
}
|
||||
};
|
||||
|
||||
var actualFilterValue = INodeFilter.GetPropertyFilter(nonLikeFilter, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.That(actualFilterValue, Is.EqualTo(expectedFilterValue));
|
||||
|
||||
var likeFilter = new List<NodePropertyFilter>
|
||||
{
|
||||
new NodePropertyFilter()
|
||||
{
|
||||
Property = "Name",
|
||||
Type = typeof(string),
|
||||
ValidFor = ValidForFlag.All,
|
||||
Values = new List<object> { input },
|
||||
FilterType = FilterType.STARTSWITH,
|
||||
IsDateTime = false
|
||||
}
|
||||
};
|
||||
|
||||
var actualLikeFilterValue = INodeFilter.GetPropertyFilter(likeFilter, typeof(SqlHistoryTableQuerier), ValidForFlag.All);
|
||||
Assert.That(actualLikeFilterValue, Is.EqualTo(expectedLikeFilterValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user