Skip to content

Commit 8662001

Browse files
committed
CSHARP-4861: Count comparison with constant on the left is not translated correctly.
1 parent 8365a61 commit 8662001

File tree

4 files changed

+131
-18
lines changed

4 files changed

+131
-18
lines changed

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionTranslators/ArrayLengthComparisonExpressionToFilterTranslator.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,32 +38,32 @@ public static bool CanTranslate(Expression leftExpression, Expression rightExpre
3838
return false;
3939
}
4040

41-
public static AstFilter Translate(TranslationContext context, BinaryExpression expression, UnaryExpression arrayLengthExpression, Expression sizeExpression)
41+
public static AstFilter Translate(TranslationContext context, BinaryExpression expression, AstComparisonFilterOperator comparisonOperator, UnaryExpression arrayLengthExpression, Expression sizeExpression)
4242
{
4343
if (arrayLengthExpression.NodeType == ExpressionType.ArrayLength)
4444
{
4545
var arrayExpression = arrayLengthExpression.Operand;
4646
var arrayField = ExpressionToFilterFieldTranslator.Translate(context, arrayExpression);
4747
var size = sizeExpression.GetConstantValue<int>(containingExpression: expression);
4848

49-
switch (expression.NodeType)
49+
switch (comparisonOperator)
5050
{
51-
case ExpressionType.Equal:
51+
case AstComparisonFilterOperator.Eq:
5252
return AstFilter.Size(arrayField, size);
5353

54-
case ExpressionType.GreaterThan:
54+
case AstComparisonFilterOperator.Gt:
5555
return AstFilter.Exists(ItemField(arrayField, size));
5656

57-
case ExpressionType.GreaterThanOrEqual:
57+
case AstComparisonFilterOperator.Gte:
5858
return AstFilter.Exists(ItemField(arrayField, size - 1));
5959

60-
case ExpressionType.LessThan:
60+
case AstComparisonFilterOperator.Lt:
6161
return AstFilter.NotExists(ItemField(arrayField, size - 1));
6262

63-
case ExpressionType.LessThanOrEqual:
63+
case AstComparisonFilterOperator.Lte:
6464
return AstFilter.NotExists(ItemField(arrayField, size));
6565

66-
case ExpressionType.NotEqual:
66+
case AstComparisonFilterOperator.Ne:
6767
return AstFilter.Not(AstFilter.Size(arrayField, size));
6868
}
6969

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionTranslators/ComparisonExpressionToFilterTranslator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public static AstFilter Translate(TranslationContext context, BinaryExpression e
3838

3939
if (ArrayLengthComparisonExpressionToFilterTranslator.CanTranslate(leftExpression, rightExpression, out var arrayLengthExpression, out var sizeExpression))
4040
{
41-
return ArrayLengthComparisonExpressionToFilterTranslator.Translate(context, expression, arrayLengthExpression, sizeExpression);
41+
return ArrayLengthComparisonExpressionToFilterTranslator.Translate(context, expression, comparisonOperator, arrayLengthExpression, sizeExpression);
4242
}
4343

4444
if (BitMaskComparisonExpressionToFilterTranslator.CanTranslate(leftExpression, rightExpression))
@@ -53,7 +53,7 @@ public static AstFilter Translate(TranslationContext context, BinaryExpression e
5353

5454
if (CountComparisonExpressionToFilterTranslator.CanTranslate(leftExpression, rightExpression, out var countExpression, out sizeExpression))
5555
{
56-
return CountComparisonExpressionToFilterTranslator.Translate(context, expression, countExpression, sizeExpression);
56+
return CountComparisonExpressionToFilterTranslator.Translate(context, expression, comparisonOperator, countExpression, sizeExpression);
5757
}
5858

5959
if (GetTypeComparisonExpressionToFilterTranslator.CanTranslate(leftExpression, rightExpression))

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionTranslators/CountComparisonExpressionToFilterTranslator.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,31 +59,31 @@ public static bool CanTranslate(Expression leftExpression, Expression rightExpre
5959
return false;
6060
}
6161

62-
public static AstFilter Translate(TranslationContext context, BinaryExpression expression, Expression enumerableExpression, Expression sizeExpression)
62+
public static AstFilter Translate(TranslationContext context, BinaryExpression expression, AstComparisonFilterOperator comparisonOperator, Expression enumerableExpression, Expression sizeExpression)
6363
{
6464
var field = ExpressionToFilterFieldTranslator.Translate(context, enumerableExpression);
6565
SerializationHelper.EnsureRepresentationIsArray(enumerableExpression, field.Serializer);
6666

6767
if (TryConvertSizeExpressionToBsonValue(sizeExpression, out var size))
6868
{
69-
switch (expression.NodeType)
69+
switch (comparisonOperator)
7070
{
71-
case ExpressionType.Equal:
71+
case AstComparisonFilterOperator.Eq:
7272
return AstFilter.Size(field, size);
7373

74-
case ExpressionType.GreaterThan:
74+
case AstComparisonFilterOperator.Gt:
7575
return AstFilter.Exists(ItemField(field, size.ToInt64()));
7676

77-
case ExpressionType.GreaterThanOrEqual:
77+
case AstComparisonFilterOperator.Gte:
7878
return AstFilter.Exists(ItemField(field, size.ToInt64() - 1));
7979

80-
case ExpressionType.LessThan:
80+
case AstComparisonFilterOperator.Lt:
8181
return AstFilter.NotExists(ItemField(field, size.ToInt64() - 1));
8282

83-
case ExpressionType.LessThanOrEqual:
83+
case AstComparisonFilterOperator.Lte:
8484
return AstFilter.NotExists(ItemField(field, size.ToInt64()));
8585

86-
case ExpressionType.NotEqual:
86+
case AstComparisonFilterOperator.Ne:
8787
return AstFilter.Not(AstFilter.Size(field, size));
8888
}
8989
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/* Copyright 2010-present MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System.Collections.Generic;
17+
using System.Linq;
18+
using FluentAssertions;
19+
using MongoDB.Driver.Linq;
20+
using MongoDB.TestHelpers.XunitExtensions;
21+
using Xunit;
22+
23+
namespace MongoDB.Driver.Tests.Linq.Linq3Implementation.Jira
24+
{
25+
public class CSharp4861Tests : Linq3IntegrationTest
26+
{
27+
[Theory]
28+
[ParameterAttributeData]
29+
public void One_less_than_Count_should_work(
30+
[Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider)
31+
{
32+
var collection = GetCollection(linqProvider);
33+
34+
var queryable = collection.AsQueryable()
35+
.Where(x => 1 < x.Set.Count);
36+
37+
var stages = Translate(collection, queryable);
38+
AssertStages(stages, "{ $match : { 'Set.1' : { $exists : true } } }");
39+
40+
var results = queryable.ToList();
41+
results.Select(x => x.Id).Should().Equal(2, 3);
42+
}
43+
44+
[Theory]
45+
[ParameterAttributeData]
46+
public void One_less_than_Length_should_work(
47+
[Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider)
48+
{
49+
var collection = GetCollection(linqProvider);
50+
51+
var queryable = collection.AsQueryable()
52+
.Where(x => 1 < x.Array.Length);
53+
54+
var stages = Translate(collection, queryable);
55+
AssertStages(stages, "{ $match : { 'Array.1' : { $exists : true } } }");
56+
57+
var results = queryable.ToList();
58+
results.Select(x => x.Id).Should().Equal(2, 3);
59+
}
60+
61+
[Theory]
62+
[ParameterAttributeData]
63+
public void Count_greater_than_one_should_work(
64+
[Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider)
65+
{
66+
var collection = GetCollection(linqProvider);
67+
68+
var queryable = collection.AsQueryable()
69+
.Where(x => x.Set.Count > 1);
70+
71+
var stages = Translate(collection, queryable);
72+
AssertStages(stages, "{ $match : { 'Set.1' : { $exists : true } } }");
73+
74+
var results = queryable.ToList();
75+
results.Select(x => x.Id).Should().Equal(2, 3);
76+
}
77+
78+
[Theory]
79+
[ParameterAttributeData]
80+
public void Length_greater_than_one_should_work(
81+
[Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider)
82+
{
83+
var collection = GetCollection(linqProvider);
84+
85+
var queryable = collection.AsQueryable()
86+
.Where(x => x.Array.Length > 1);
87+
88+
var stages = Translate(collection, queryable);
89+
AssertStages(stages, "{ $match : { 'Array.1' : { $exists : true } } }");
90+
91+
var results = queryable.ToList();
92+
results.Select(x => x.Id).Should().Equal(2, 3);
93+
}
94+
95+
private IMongoCollection<C> GetCollection(LinqProvider linqProvider)
96+
{
97+
var collection = GetCollection<C>("test", linqProvider);
98+
CreateCollection(
99+
collection,
100+
new C { Id = 1, Array = new[] { 1 }, Set = new HashSet<int> { 1 } },
101+
new C { Id = 2, Array = new[] { 1, 2 }, Set = new HashSet<int> { 1, 2 } },
102+
new C { Id = 3, Array = new[] { 1, 2, 3 }, Set = new HashSet<int> { 1, 2, 3 } });
103+
return collection;
104+
}
105+
106+
private class C
107+
{
108+
public int Id { get; set; }
109+
public int[] Array { get; set; }
110+
public HashSet<int> Set { get; set; }
111+
}
112+
}
113+
}

0 commit comments

Comments
 (0)