Skip to content

Commit 25dd800

Browse files
committed
CSHARP-4878: Implement Repeat in nested LINQ expressions.
1 parent 1d51d7b commit 25dd800

File tree

3 files changed

+152
-0
lines changed

3 files changed

+152
-0
lines changed

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodCallExpressionToAggregationExpressionTranslator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public static AggregationExpression Translate(TranslationContext context, Method
6868
case "Push": return PushMethodToAggregationExpressionTranslator.Translate(context, expression);
6969
case "Range": return RangeMethodToAggregationExpressionTranslator.Translate(context, expression);
7070
case "Rank": return RankMethodToAggregationExpressionTranslator.Translate(context, expression);
71+
case "Repeat": return RepeatMethodToAggregationExpressionTranslator.Translate(context, expression);
7172
case "Reverse": return ReverseMethodToAggregationExpressionTranslator.Translate(context, expression);
7273
case "Round": return RoundMethodToAggregationExpressionTranslator.Translate(context, expression);
7374
case "Select": return SelectMethodToAggregationExpressionTranslator.Translate(context, expression);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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.Linq.Expressions;
17+
using System.Reflection;
18+
using MongoDB.Driver.Linq.Linq3Implementation.Ast.Expressions;
19+
using MongoDB.Driver.Linq.Linq3Implementation.Misc;
20+
using MongoDB.Driver.Linq.Linq3Implementation.Reflection;
21+
using MongoDB.Driver.Linq.Linq3Implementation.Serializers;
22+
23+
namespace MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.MethodTranslators
24+
{
25+
internal static class RepeatMethodToAggregationExpressionTranslator
26+
{
27+
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
28+
{
29+
var method = expression.Method;
30+
var arguments = expression.Arguments;
31+
32+
if (method.Is(EnumerableMethod.Repeat))
33+
{
34+
var elementExpression = arguments[0];
35+
var countExpression = arguments[1];
36+
37+
var elementTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, elementExpression);
38+
var countTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, countExpression);
39+
40+
var (elementVarBinding, elementAst) = AstExpression.UseVarIfNotSimple("element", elementTranslation.Ast);
41+
var ast = AstExpression.Let(
42+
var: elementVarBinding,
43+
@in: AstExpression.Map(
44+
input: AstExpression.Range(0, countTranslation.Ast),
45+
@as: AstExpression.Var("i"),
46+
@in: elementAst));
47+
48+
var resultSerializer = IEnumerableSerializer.Create(elementTranslation.Serializer);
49+
return new AggregationExpression(expression, ast, resultSerializer);
50+
}
51+
52+
throw new ExpressionNotSupportedException(expression);
53+
}
54+
}
55+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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.Linq;
17+
using FluentAssertions;
18+
using Xunit;
19+
20+
namespace MongoDB.Driver.Tests.Linq.Linq3Implementation.Jira
21+
{
22+
public class CSharp4878Tests : Linq3IntegrationTest
23+
{
24+
[Fact]
25+
public void Repeat_with_constant_and_constant_should_work()
26+
{
27+
var collection = GetCollection();
28+
29+
var queryable = collection.AsQueryable().Select(x => Enumerable.Repeat(2, 3));
30+
31+
var stages = Translate(collection, queryable);
32+
AssertStages(stages, "{ $project : { _v : [2, 2, 2], _id : 0 } }");
33+
34+
var result = queryable.First();
35+
result.Should().Equal(2, 2, 2);
36+
}
37+
38+
[Fact]
39+
public void Repeat_with_constant_and_expression_should_work()
40+
{
41+
var collection = GetCollection();
42+
43+
var queryable = collection.AsQueryable().Select(x => Enumerable.Repeat(2, x.Y));
44+
45+
var stages = Translate(collection, queryable);
46+
AssertStages(stages, "{ $project : { _v : { $map : { input : { $range : [0, '$Y'] }, as : 'i', in : 2 } }, _id : 0 } }");
47+
48+
var result = queryable.First();
49+
result.Should().Equal(2, 2, 2);
50+
}
51+
52+
[Fact]
53+
public void Repeat_with_expression_and_constant_should_work()
54+
{
55+
var collection = GetCollection();
56+
57+
var queryable = collection.AsQueryable().Select(x => Enumerable.Repeat(x.X, 3));
58+
59+
var stages = Translate(collection, queryable);
60+
AssertStages(stages, "{ $project : { _v : { $map : { input : { $range : [0, 3] }, as : 'i', in : '$X' } }, _id : 0 } }");
61+
62+
var result = queryable.First();
63+
result.Should().Equal(2, 2, 2);
64+
}
65+
66+
[Fact]
67+
public void Repeat_with_expression_and_expression_should_work()
68+
{
69+
var collection = GetCollection();
70+
71+
var queryable = collection.AsQueryable().Select(x => Enumerable.Repeat(x.X, x.Y));
72+
73+
var stages = Translate(collection, queryable);
74+
AssertStages(stages, "{ $project : { _v : { $map : { input : { $range : [0, '$Y'] }, as : 'i', in : '$X' } }, _id : 0 } }");
75+
76+
var result = queryable.First();
77+
result.Should().Equal(2, 2, 2);
78+
}
79+
80+
private IMongoCollection<C> GetCollection()
81+
{
82+
var collection = GetCollection<C>("test");
83+
CreateCollection(
84+
collection,
85+
new C { Id = 1, X = 2, Y = 3 });
86+
return collection;
87+
}
88+
89+
private class C
90+
{
91+
public int Id { get; set; }
92+
public int X { get; set; }
93+
public int Y { get; set; }
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)