stop excluding null values when filtering using notEqual (#114)

* stop excluding null values when filtering using notEqual
* add IgnoreNullsOnNotEqual config field, to enable/disable the new feature

Co-authored-by: AnasZakarneh <a.zakarneh@foothillsolutions.com>
This commit is contained in:
AnasZakarneh 2021-05-24 20:24:18 +03:00 committed by GitHub
parent 7542ec0fbf
commit aaedf7a684
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 9 deletions

View File

@ -127,7 +127,8 @@ Then you can add the configuration:
"CaseSensitive": "boolean: should property names be case-sensitive? Defaults to false", "CaseSensitive": "boolean: should property names be case-sensitive? Defaults to false",
"DefaultPageSize": "int number: optional number to fallback to when no page argument is given. Set <=0 to disable paging if no pageSize is specified (default).", "DefaultPageSize": "int number: optional number to fallback to when no page argument is given. Set <=0 to disable paging if no pageSize is specified (default).",
"MaxPageSize": "int number: maximum allowed page size. Set <=0 to make infinite (default)", "MaxPageSize": "int number: maximum allowed page size. Set <=0 to make infinite (default)",
"ThrowExceptions": "boolean: should Sieve throw exceptions instead of silently failing? Defaults to false" "ThrowExceptions": "boolean: should Sieve throw exceptions instead of silently failing? Defaults to false",
"IgnoreNullsOnNotEqual": "boolean: ignore null values when filtering using is not equal operator? Default to true"
} }
} }
``` ```

View File

@ -4,7 +4,8 @@
}, },
"Sieve": { "Sieve": {
"CaseSensitive": false, "CaseSensitive": false,
"DefaultPageSize": 10 "DefaultPageSize": 10,
"IgnoreNullsOnNotEqual": true
}, },
"Logging": { "Logging": {
"Debug": { "Debug": {

View File

@ -9,5 +9,7 @@
public int MaxPageSize { get; set; } = 0; public int MaxPageSize { get; set; } = 0;
public bool ThrowExceptions { get; set; } = false; public bool ThrowExceptions { get; set; } = false;
public bool IgnoreNullsOnNotEqual { get; set; } = true;
} }
} }

View File

@ -217,11 +217,14 @@ namespace Sieve.Services
expression = Expression.Not(expression); expression = Expression.Not(expression);
} }
if (expression.NodeType != ExpressionType.NotEqual || Options.Value.IgnoreNullsOnNotEqual)
{
var filterValueNullCheck = GetFilterValueNullCheck(parameter, fullPropertyName, isFilterTermValueNull); var filterValueNullCheck = GetFilterValueNullCheck(parameter, fullPropertyName, isFilterTermValueNull);
if (filterValueNullCheck != null) if (filterValueNullCheck != null)
{ {
expression = Expression.AndAlso(filterValueNullCheck, expression); expression = Expression.AndAlso(filterValueNullCheck, expression);
} }
}
innerExpression = innerExpression == null innerExpression = innerExpression == null
? expression ? expression
@ -254,8 +257,7 @@ namespace Sieve.Services
: result.Where(Expression.Lambda<Func<TEntity, bool>>(outerExpression, parameter)); : result.Where(Expression.Lambda<Func<TEntity, bool>>(outerExpression, parameter));
} }
private static Expression GetFilterValueNullCheck(Expression parameter, string fullPropertyName, private static Expression GetFilterValueNullCheck(Expression parameter, string fullPropertyName, bool isFilterTermValueNull)
bool isFilterTermValueNull)
{ {
var (propertyValue, nullCheck) = GetPropertyValueAndNullCheckExpression(parameter, fullPropertyName); var (propertyValue, nullCheck) = GetPropertyValueAndNullCheckExpression(parameter, fullPropertyName);

View File

@ -15,16 +15,24 @@ namespace SieveUnitTests
{ {
private readonly ITestOutputHelper _testOutputHelper; private readonly ITestOutputHelper _testOutputHelper;
private readonly SieveProcessor _processor; private readonly SieveProcessor _processor;
private readonly SieveProcessor _nullableProcessor;
private readonly IQueryable<Post> _posts; private readonly IQueryable<Post> _posts;
private readonly IQueryable<Comment> _comments; private readonly IQueryable<Comment> _comments;
public General(ITestOutputHelper testOutputHelper) public General(ITestOutputHelper testOutputHelper)
{ {
var nullableAccessor = new SieveOptionsAccessor();
nullableAccessor.Value.IgnoreNullsOnNotEqual = false;
_testOutputHelper = testOutputHelper; _testOutputHelper = testOutputHelper;
_processor = new ApplicationSieveProcessor(new SieveOptionsAccessor(), _processor = new ApplicationSieveProcessor(new SieveOptionsAccessor(),
new SieveCustomSortMethods(), new SieveCustomSortMethods(),
new SieveCustomFilterMethods()); new SieveCustomFilterMethods());
_nullableProcessor = new ApplicationSieveProcessor(nullableAccessor,
new SieveCustomSortMethods(),
new SieveCustomFilterMethods());
_posts = new List<Post> _posts = new List<Post>
{ {
new Post new Post
@ -180,8 +188,25 @@ namespace SieveUnitTests
}; };
var result = _processor.Apply(model, _posts); var result = _processor.Apply(model, _posts);
var nullableResult = _nullableProcessor.Apply(model, _posts);
Assert.True(result.Count() == 2); Assert.True(result.Count() == 2);
Assert.True(nullableResult.Count() == 2);
}
[Fact]
public void CanFilterNullableIntsWithNotEqual()
{
var model = new SieveModel()
{
Filters = "CategoryId!=1"
};
var result = _processor.Apply(model, _posts);
var nullableResult = _nullableProcessor.Apply(model, _posts);
Assert.True(result.Count() == 1);
Assert.True(nullableResult.Count() == 2);
} }
[Theory] [Theory]

View File

@ -16,16 +16,24 @@ namespace SieveUnitTests
{ {
private readonly ITestOutputHelper _testOutputHelper; private readonly ITestOutputHelper _testOutputHelper;
private readonly SieveProcessor _processor; private readonly SieveProcessor _processor;
private readonly SieveProcessor _nullableProcessor;
private readonly IQueryable<IPost> _posts; private readonly IQueryable<IPost> _posts;
private readonly IQueryable<Comment> _comments; private readonly IQueryable<Comment> _comments;
public GeneralWithInterfaces(ITestOutputHelper testOutputHelper) public GeneralWithInterfaces(ITestOutputHelper testOutputHelper)
{ {
var nullableAccessor = new SieveOptionsAccessor();
nullableAccessor.Value.IgnoreNullsOnNotEqual = false;
_testOutputHelper = testOutputHelper; _testOutputHelper = testOutputHelper;
_processor = new ApplicationSieveProcessor(new SieveOptionsAccessor(), _processor = new ApplicationSieveProcessor(new SieveOptionsAccessor(),
new SieveCustomSortMethods(), new SieveCustomSortMethods(),
new SieveCustomFilterMethods()); new SieveCustomFilterMethods());
_nullableProcessor = new ApplicationSieveProcessor(nullableAccessor,
new SieveCustomSortMethods(),
new SieveCustomFilterMethods());
_posts = new List<IPost> _posts = new List<IPost>
{ {
new Post new Post
@ -181,8 +189,25 @@ namespace SieveUnitTests
}; };
var result = _processor.Apply(model, _posts); var result = _processor.Apply(model, _posts);
var nullableResult = _nullableProcessor.Apply(model, _posts);
Assert.True(result.Count() == 2); Assert.True(result.Count() == 2);
Assert.True(nullableResult.Count() == 2);
}
[Fact]
public void CanFilterNullableIntsWithNotEqual()
{
var model = new SieveModel()
{
Filters = "CategoryId!=1"
};
var result = _processor.Apply(model, _posts);
var nullableResult = _nullableProcessor.Apply(model, _posts);
Assert.True(result.Count() == 1);
Assert.True(nullableResult.Count() == 2);
} }
[Fact] [Fact]