Skip to content

Commit 3a85339

Browse files
committed
CSHARP-5730: Work in progress to fully support Compare.
1 parent fb728dc commit 3a85339

File tree

4 files changed

+85
-43
lines changed

4 files changed

+85
-43
lines changed

src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Filters/AstFilter.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,31 @@ public static AstFilterField Field(string path)
139139
return new AstFilterField(path);
140140
}
141141

142+
public static AstFieldOperationFilter Gt(AstFilterField field, BsonValue value)
143+
{
144+
return new AstFieldOperationFilter(field, new AstComparisonFilterOperation(AstComparisonFilterOperator.Gt, value));
145+
}
146+
147+
public static AstFieldOperationFilter Gte(AstFilterField field, BsonValue value)
148+
{
149+
return new AstFieldOperationFilter(field, new AstComparisonFilterOperation(AstComparisonFilterOperator.Gte, value));
150+
}
151+
142152
public static AstFieldOperationFilter In(AstFilterField field, IEnumerable<BsonValue> values)
143153
{
144154
return new AstFieldOperationFilter(field, new AstInFilterOperation(values));
145155
}
146156

157+
public static AstFieldOperationFilter Lt(AstFilterField field, BsonValue value)
158+
{
159+
return new AstFieldOperationFilter(field, new AstComparisonFilterOperation(AstComparisonFilterOperator.Lt, value));
160+
}
161+
162+
public static AstFieldOperationFilter Lte(AstFilterField field, BsonValue value)
163+
{
164+
return new AstFieldOperationFilter(field, new AstComparisonFilterOperation(AstComparisonFilterOperator.Lte, value));
165+
}
166+
147167
public static AstFilter MatchesEverything()
148168
{
149169
return new AstMatchesEverythingFilter();

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/CompareMethodToAggregationExpressionTranslator.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,13 @@ public static TranslatedExpression Translate(TranslationContext context, MethodC
3030
if (method.Is(StringMethod.StaticCompare))
3131
{
3232
var strAExpression = arguments[0];
33-
var strATranslation = ExpressionToAggregationExpressionTranslator.Translate(context, strAExpression);
3433
var strBExpression = arguments[1];
34+
35+
var strATranslation = ExpressionToAggregationExpressionTranslator.Translate(context, strAExpression);
3536
var strBTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, strBExpression);
37+
3638
var ast = AstExpression.Cmp(strATranslation.Ast, strBTranslation.Ast);
39+
3740
return new TranslatedExpression(expression, ast, Int32Serializer.Instance);
3841
}
3942

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,22 @@ public static AstFilter Translate(
6666
var serializedValue = SerializationHelper.SerializeValue(fieldTranslation.Serializer, value);
6767

6868
var rightValue = rightExpression.GetConstantValue<int>(containingExpression: expression);
69-
if (rightValue == 0)
69+
return (comparisonOperator, rightValue) switch
7070
{
71-
return AstFilter.Compare(fieldTranslation.Ast, comparisonOperator, serializedValue);
72-
}
71+
(AstComparisonFilterOperator.Eq, -1) => AstFilter.Lt(fieldTranslation.Ast, serializedValue),
72+
(AstComparisonFilterOperator.Ne, -1) => AstFilter.Gte(fieldTranslation.Ast, serializedValue),
73+
(AstComparisonFilterOperator.Gt, -1) => AstFilter.Gte(fieldTranslation.Ast, serializedValue),
74+
(AstComparisonFilterOperator.Eq, 0) => AstFilter.Eq(fieldTranslation.Ast, serializedValue),
75+
(AstComparisonFilterOperator.Ne, 0) => AstFilter.Ne(fieldTranslation.Ast, serializedValue),
76+
(AstComparisonFilterOperator.Lt, 0) => AstFilter.Lt(fieldTranslation.Ast, serializedValue),
77+
(AstComparisonFilterOperator.Lte, 0) => AstFilter.Lte(fieldTranslation.Ast, serializedValue),
78+
(AstComparisonFilterOperator.Gt, 0) => AstFilter.Gt(fieldTranslation.Ast, serializedValue),
79+
(AstComparisonFilterOperator.Gte, 0) => AstFilter.Gte(fieldTranslation.Ast, serializedValue),
80+
(AstComparisonFilterOperator.Eq, 1) => AstFilter.Gt(fieldTranslation.Ast, serializedValue),
81+
(AstComparisonFilterOperator.Ne, 1) => AstFilter.Lte(fieldTranslation.Ast, serializedValue),
82+
(AstComparisonFilterOperator.Lt, 1) => AstFilter.Lte(fieldTranslation.Ast, serializedValue),
83+
_ => throw new ExpressionNotSupportedException(expression)
84+
};
7385
}
7486

7587
throw new ExpressionNotSupportedException(expression);

tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5730Tests.cs

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
* limitations under the License.
1414
*/
1515

16+
using System;
1617
using System.Collections.Generic;
1718
using System.Linq;
19+
using System.Linq.Expressions;
1820
using MongoDB.Driver.TestHelpers;
1921
using FluentAssertions;
2022
using Xunit;
@@ -28,65 +30,70 @@ public CSharp5730Tests(ClassFixture fixture)
2830
{
2931
}
3032

31-
[Fact]
32-
public void Where_String_Compare_greater_than_zero_should_work()
33+
[Theory]
34+
[InlineData( 1, "{ $match : { A : { $lt : 'B' } } }", new int[] { 1, 2 })]
35+
[InlineData( 2, "{ $match : { A : 'B' } }", new int[] { 3 })]
36+
[InlineData( 3, "{ $match : { A : { $gt : 'B' } } }", new int[] { 4, 5, 6 })]
37+
[InlineData( 4, "{ $match : { A : { $gte : 'B' } } }", new int[] { 3, 4, 5, 6 })]
38+
[InlineData( 5, "{ $match : { A : { $ne : 'B' } } }", new int[] { 1, 2, 4, 5, 6 })]
39+
[InlineData( 6, "{ $match : { A : { $lte : 'B' } } }", new int[] { 1, 2, 3 })]
40+
[InlineData( 7, "{ $match : { A : { $gte : 'B' } } }", new int[] { 3, 4, 5, 6 })]
41+
[InlineData( 8, "{ $match : { A : { $gt : 'B' } } }", new int[] { 4, 5, 6 })]
42+
[InlineData( 9, "{ $match : { A : { $lt : 'B' } } }", new int[] { 1, 2 })]
43+
[InlineData(10, "{ $match : { A : { $lte : 'B' } } }", new int[] { 1, 2, 3 })]
44+
[InlineData(11, "{ $match : { A : { $lte : 'B' } } }", new int[] { 1, 2, 3 })]
45+
[InlineData(12, "{ $match : { A : { $gte : 'B' } } }", new int[] { 1, 3, 4, 5, 6 })]
46+
public void Where_String_Compare_field_to_constant_should_work(int scenario, string expectedStage, int[] expectedResults)
3347
{
3448
var collection = Fixture.Collection;
3549

36-
var queryable = collection.AsQueryable()
37-
.Where(d => string.Compare(d.Key, "a4e48b55-0519-4ab3-b6b9-7c532fc65b56") > 0);
38-
39-
var stages = Translate(collection, queryable);
40-
AssertStages(stages, "{ $match : { Key : { $gt : 'a4e48b55-0519-4ab3-b6b9-7c532fc65b56' } } }");
41-
42-
var result = queryable.ToList();
43-
result.Select(x => x. Id).Should().Equal(4);
44-
}
45-
46-
[Fact]
47-
public void Where_String_CompareTo_greater_than_zero_should_work()
48-
{
49-
var collection = Fixture.Collection;
50-
51-
var queryable = collection.AsQueryable()
52-
.Where(d => d.Key.CompareTo("a4e48b55-0519-4ab3-b6b9-7c532fc65b56") > 0);
53-
54-
var stages = Translate(collection, queryable);
55-
AssertStages(stages, "{ $match : { Key : { $gt : 'a4e48b55-0519-4ab3-b6b9-7c532fc65b56' } } }");
56-
57-
var result = queryable.ToList();
58-
result.Select(x => x. Id).Should().Equal(4);
50+
var queryable = scenario switch
51+
{
52+
// Compare field to constant
53+
1 => collection.AsQueryable().Where(x => string.Compare(x.A, "B") == -1),
54+
2 => collection.AsQueryable().Where(x => string.Compare(x.A, "B") == 0),
55+
3 => collection.AsQueryable().Where(x => string.Compare(x.A, "B") == 1),
56+
4 => collection.AsQueryable().Where(x => string.Compare(x.A, "B") != -1),
57+
5 => collection.AsQueryable().Where(x => string.Compare(x.A, "B") != 0),
58+
6 => collection.AsQueryable().Where(x => string.Compare(x.A, "B") != 1),
59+
7 => collection.AsQueryable().Where(x => string.Compare(x.A, "B") > -1),
60+
8 => collection.AsQueryable().Where(x => string.Compare(x.A, "B") > 0),
61+
9 => collection.AsQueryable().Where(x => string.Compare(x.A, "B") < 0),
62+
10 => collection.AsQueryable().Where(x => string.Compare(x.A, "B") < 1),
63+
11 => collection.AsQueryable().Where(x => string.Compare(x.A, "B") <= 0),
64+
12 => collection.AsQueryable().Where(x => string.Compare(x.A, "B") >= 0),
65+
_ => throw new ArgumentException($"Invalid scenario: {scenario}.")
66+
};
67+
68+
Assert(collection, queryable, expectedStage, expectedResults);
5969
}
6070

61-
[Fact]
62-
public void Select_String_Compare_should_work()
71+
private void Assert(IMongoCollection<C> collection, IQueryable<C> queryable, string expectedStage, int[] expectedResults)
6372
{
64-
var collection = Fixture.Collection;
65-
66-
var queryable = collection.AsQueryable()
67-
.Select(d => string.Compare(d.Key, "a4e48b55-0519-4ab3-b6b9-7c532fc65b56") > 0);
68-
6973
var stages = Translate(collection, queryable);
70-
AssertStages(stages, "{ $project : { _v : { $gt : [{ $cmp : ['$Key', 'a4e48b55-0519-4ab3-b6b9-7c532fc65b56'] }, 0] }, _id : 0 } }");
74+
AssertStages(stages, expectedStage);
7175

7276
var results = queryable.ToList();
73-
results.Should().Equal(false, false, false, true);
77+
results.Select(x => x.Id).Should().Equal(expectedResults);
7478
}
7579

7680
public class C
7781
{
7882
public int Id { get; set; }
79-
public string Key { get; set; }
83+
public string A { get; set; }
84+
public string B { get; set; }
8085
}
8186

8287
public sealed class ClassFixture : MongoCollectionFixture<C>
8388
{
8489
protected override IEnumerable<C> InitialData =>
8590
[
86-
new C { Id = 1, Key = "1b2bc240-ec2a-4a17-8790-8407e3bbb847"},
87-
new C { Id = 2, Key = "a4e48b55-0519-4ab3-b6b9-7c532fc65b56"},
88-
new C { Id = 3, Key = "9ff72c5d-189e-4511-b7ad-3f83489e4ea4"},
89-
new C { Id = 4, Key = "d78ca958-abac-46cd-94a7-fbf7a2ba683d"}
91+
new C { Id = 1, A = "A", B = "A" },
92+
new C { Id = 2, A = "A", B = "B" },
93+
new C { Id = 3, A = "B", B = "A" },
94+
new C { Id = 4, A = "a", B = "a" },
95+
new C { Id = 5, A = "a", B = "b" },
96+
new C { Id = 6, A = "b", B = "a" }
9097
];
9198
}
9299
}

0 commit comments

Comments
 (0)