Skip to content

Commit 1575f58

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 339874f commit 1575f58

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
@@ -277,10 +277,11 @@ protected override string VisitLambdaExpression(LambdaExpression topExpression,
277277

278278
private bool HasParenthesis(ExpressionType expressionType)
279279
{
280-
var hasParenthesis = _expressionType.HasValue && expressionType switch
280+
281+
var hasParenthesis = expressionType switch
281282
{
282-
ExpressionType.And => true,
283-
ExpressionType.AndAlso => true,
283+
ExpressionType.And => true && _expressionType.HasValue,
284+
ExpressionType.AndAlso => true && _expressionType.HasValue,
284285
ExpressionType.Or => true,
285286
ExpressionType.OrElse => true,
286287
_ => false,

test/OData.QueryBuilder.Test/ODataQueryCollectionTest.cs

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

1173+
[Fact(DisplayName = "Multiple filters wrap or in parenthesis => Success")]
1174+
public void ODataQueryBuilderList_Multiple_filters_wrap_or_in_parenthesis_Success()
1175+
{
1176+
var constStrIds = new[] { "123", "512" };
1177+
var constValue = 3;
1178+
1179+
var uri = _odataQueryBuilderDefault
1180+
.For<ODataTypeEntity>(s => s.ODataType)
1181+
.ByList()
1182+
.Filter((s, f, o) => s.IdRule == constValue)
1183+
.Filter((s, f, o) => s.IsActive)
1184+
.Filter((s, f, o) => (f.Date(s.EndDate.Value) == default(DateTimeOffset?) || s.EndDate > DateTime.Today), useParenthesis: true)
1185+
.Filter((s, f, o) => (f.Date((DateTimeOffset)s.BeginDate) != default(DateTime?) || f.Date((DateTime)s.BeginDate) <= DateTime.Now), useParenthesis: true)
1186+
.Filter((s, f, o) => (o.In(s.ODataKind.ODataCode.Code, constStrIds)))
1187+
.ToUri();
1188+
1189+
uri.Should().Be($"http://mock/odata/ODataType?$filter=IdRule eq 3" +
1190+
$" and IsActive" +
1191+
$" and (date(EndDate) eq null or EndDate gt {DateTime.Today:s}Z)" +
1192+
$" and (date(BeginDate) ne null or date(BeginDate) le {DateTime.Now:s}Z)" +
1193+
$" and ODataKind/ODataCode/Code in ('123','512')");
1194+
}
1195+
11731196
[Theory(DisplayName = "Count value => Success")]
11741197
[InlineData(true)]
11751198
[InlineData(false)]

0 commit comments

Comments
 (0)