Skip to content

Commit 11c5a1e

Browse files
committed
Add parenthesis on filter
When combining several filters by calling Filter() multiple times, they will be joined by "and" which is "fine". The issues comes when there's an or in one of the filters, which will produce unexpected results. e.g. Filter(x => x.Foo == "some string") Filter(x => x.Bar == 1 || x.Bar == 2 ) Should be: "(Foo eq 'some string') and (Bar eq 1 or Bar eq 2)" But will be: "Foo eq 'some string' and Bar eq 1 or Bar eq 2"
1 parent 0168279 commit 11c5a1e

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

src/OData.QueryBuilder/Expressions/Visitors/ODataOptionFilterExpressionVisitor.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,11 @@ protected override string VisitLambdaExpression(LambdaExpression lambdaExpressio
254254

255255
private bool HasParenthesis(ExpressionType expressionType)
256256
{
257-
var hasParenthesis = _expressionType.HasValue && expressionType switch
257+
258+
var hasParenthesis = expressionType switch
258259
{
259-
ExpressionType.And => true,
260-
ExpressionType.AndAlso => true,
260+
ExpressionType.And => true && _expressionType.HasValue,
261+
ExpressionType.AndAlso => true && _expressionType.HasValue,
261262
ExpressionType.Or => true,
262263
ExpressionType.OrElse => true,
263264
_ => false,

test/OData.QueryBuilder.Test/ODataQueryCollectionTest.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,29 @@ public void ODataQueryBuilderList_Filter_support_parentheses_Success()
10831083
$" and ODataKind/ODataCode/Code in ('123','512')");
10841084
}
10851085

1086+
[Fact(DisplayName = "Multiple filters wrap or in parenthesis => Success")]
1087+
public void ODataQueryBuilderList_Multiple_filters_wrap_or_in_parenthesis_Success()
1088+
{
1089+
var constStrIds = new[] { "123", "512" };
1090+
var constValue = 3;
1091+
1092+
var uri = _odataQueryBuilderDefault
1093+
.For<ODataTypeEntity>(s => s.ODataType)
1094+
.ByList()
1095+
.Filter((s, f, o) => s.IdRule == constValue)
1096+
.Filter((s, f, o) => s.IsActive)
1097+
.Filter((s, f, o) => (f.Date(s.EndDate.Value) == default(DateTimeOffset?) || s.EndDate > DateTime.Today), useParenthesis: true)
1098+
.Filter((s, f, o) => (f.Date((DateTimeOffset)s.BeginDate) != default(DateTime?) || f.Date((DateTime)s.BeginDate) <= DateTime.Now), useParenthesis: true)
1099+
.Filter((s, f, o) => (o.In(s.ODataKind.ODataCode.Code, constStrIds)))
1100+
.ToUri();
1101+
1102+
uri.Should().Be($"http://mock/odata/ODataType?$filter=IdRule eq 3" +
1103+
$" and IsActive" +
1104+
$" and (date(EndDate) eq null or EndDate gt {DateTime.Today:s}Z)" +
1105+
$" and (date(BeginDate) ne null or date(BeginDate) le {DateTime.Now:s}Z)" +
1106+
$" and ODataKind/ODataCode/Code in ('123','512')");
1107+
}
1108+
10861109
[Theory(DisplayName = "Count value => Success")]
10871110
[InlineData(true)]
10881111
[InlineData(false)]

0 commit comments

Comments
 (0)