Skip to content

Commit 1577d3c

Browse files
committed
Work in progress.
1 parent 4a55bf3 commit 1577d3c

File tree

3 files changed

+115
-40
lines changed

3 files changed

+115
-40
lines changed

src/MongoDB.Driver/Linq/Linq3Implementation/KnownSerializerFinders/KnownSerializerFinderVisitBinary.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ static IBsonSerializer GetResultSerializer(Expression node, ExpressionType @oper
126126
case ExpressionType.Add:
127127
case ExpressionType.AddChecked:
128128
case ExpressionType.Divide:
129+
case ExpressionType.Modulo:
129130
case ExpressionType.Multiply:
130131
case ExpressionType.MultiplyChecked:
131132
case ExpressionType.Subtract:

src/MongoDB.Driver/Linq/Linq3Implementation/KnownSerializerFinders/KnownSerializerFinderVisitMethodCall.cs

Lines changed: 87 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ internal partial class KnownSerializerFinderVisitor
9494
QueryableMethod.Prepend
9595
];
9696

97-
private static readonly HashSet<MethodInfo> __averageMethods =
97+
private static readonly HashSet<MethodInfo> __averageOrMedianOrPercentileMethods =
9898
[
9999
EnumerableMethod.AverageDecimal,
100100
EnumerableMethod.AverageDecimalWithSelector,
@@ -135,10 +135,50 @@ internal partial class KnownSerializerFinderVisitor
135135
QueryableMethod.AverageNullableSingle,
136136
QueryableMethod.AverageNullableSingleWithSelector,
137137
QueryableMethod.AverageSingle,
138-
QueryableMethod.AverageSingleWithSelector
138+
QueryableMethod.AverageSingleWithSelector,
139+
MongoEnumerableMethod.MedianDecimal,
140+
MongoEnumerableMethod.MedianDecimalWithSelector,
141+
MongoEnumerableMethod.MedianDouble,
142+
MongoEnumerableMethod.MedianDoubleWithSelector,
143+
MongoEnumerableMethod.MedianInt32,
144+
MongoEnumerableMethod.MedianInt32WithSelector,
145+
MongoEnumerableMethod.MedianInt64,
146+
MongoEnumerableMethod.MedianInt64WithSelector,
147+
MongoEnumerableMethod.MedianNullableDecimal,
148+
MongoEnumerableMethod.MedianNullableDecimalWithSelector,
149+
MongoEnumerableMethod.MedianNullableDouble,
150+
MongoEnumerableMethod.MedianNullableDoubleWithSelector,
151+
MongoEnumerableMethod.MedianNullableInt32,
152+
MongoEnumerableMethod.MedianNullableInt32WithSelector,
153+
MongoEnumerableMethod.MedianNullableInt64,
154+
MongoEnumerableMethod.MedianNullableInt64WithSelector,
155+
MongoEnumerableMethod.MedianNullableSingle,
156+
MongoEnumerableMethod.MedianNullableSingleWithSelector,
157+
MongoEnumerableMethod.MedianSingle,
158+
MongoEnumerableMethod.MedianSingleWithSelector,
159+
MongoEnumerableMethod.PercentileDecimal,
160+
MongoEnumerableMethod.PercentileDecimalWithSelector,
161+
MongoEnumerableMethod.PercentileDouble,
162+
MongoEnumerableMethod.PercentileDoubleWithSelector,
163+
MongoEnumerableMethod.PercentileInt32,
164+
MongoEnumerableMethod.PercentileInt32WithSelector,
165+
MongoEnumerableMethod.PercentileInt64,
166+
MongoEnumerableMethod.PercentileInt64WithSelector,
167+
MongoEnumerableMethod.PercentileNullableDecimal,
168+
MongoEnumerableMethod.PercentileNullableDecimalWithSelector,
169+
MongoEnumerableMethod.PercentileNullableDouble,
170+
MongoEnumerableMethod.PercentileNullableDoubleWithSelector,
171+
MongoEnumerableMethod.PercentileNullableInt32,
172+
MongoEnumerableMethod.PercentileNullableInt32WithSelector,
173+
MongoEnumerableMethod.PercentileNullableInt64,
174+
MongoEnumerableMethod.PercentileNullableInt64WithSelector,
175+
MongoEnumerableMethod.PercentileNullableSingle,
176+
MongoEnumerableMethod.PercentileNullableSingleWithSelector,
177+
MongoEnumerableMethod.PercentileSingle,
178+
MongoEnumerableMethod.PercentileSingleWithSelector
139179
];
140180

141-
private static readonly HashSet<MethodInfo> __averageWithSelectorMethods =
181+
private static readonly HashSet<MethodInfo> __averageOrMedianOrPercentileWithSelectorMethods =
142182
[
143183
EnumerableMethod.AverageDecimalWithSelector,
144184
EnumerableMethod.AverageDoubleWithSelector,
@@ -159,7 +199,27 @@ internal partial class KnownSerializerFinderVisitor
159199
QueryableMethod.AverageNullableInt32WithSelector,
160200
QueryableMethod.AverageNullableInt64WithSelector,
161201
QueryableMethod.AverageNullableSingleWithSelector,
162-
QueryableMethod.AverageSingleWithSelector
202+
QueryableMethod.AverageSingleWithSelector,
203+
MongoEnumerableMethod.MedianDecimalWithSelector,
204+
MongoEnumerableMethod.MedianDoubleWithSelector,
205+
MongoEnumerableMethod.MedianInt32WithSelector,
206+
MongoEnumerableMethod.MedianInt64WithSelector,
207+
MongoEnumerableMethod.MedianNullableDecimalWithSelector,
208+
MongoEnumerableMethod.MedianNullableDoubleWithSelector,
209+
MongoEnumerableMethod.MedianNullableInt32WithSelector,
210+
MongoEnumerableMethod.MedianNullableInt64WithSelector,
211+
MongoEnumerableMethod.MedianNullableSingleWithSelector,
212+
MongoEnumerableMethod.MedianSingleWithSelector,
213+
MongoEnumerableMethod.PercentileDecimalWithSelector,
214+
MongoEnumerableMethod.PercentileDoubleWithSelector,
215+
MongoEnumerableMethod.PercentileInt32WithSelector,
216+
MongoEnumerableMethod.PercentileInt64WithSelector,
217+
MongoEnumerableMethod.PercentileNullableDecimalWithSelector,
218+
MongoEnumerableMethod.PercentileNullableDoubleWithSelector,
219+
MongoEnumerableMethod.PercentileNullableInt32WithSelector,
220+
MongoEnumerableMethod.PercentileNullableInt64WithSelector,
221+
MongoEnumerableMethod.PercentileNullableSingleWithSelector,
222+
MongoEnumerableMethod.PercentileSingleWithSelector
163223
];
164224

165225
private static readonly HashSet<MethodInfo> __countMethods =
@@ -358,6 +418,7 @@ internal partial class KnownSerializerFinderVisitor
358418
EnumerableMethod.MaxNullableInt64WithSelector,
359419
EnumerableMethod.MaxNullableSingleWithSelector,
360420
EnumerableMethod.MaxSingleWithSelector,
421+
EnumerableMethod.MaxWithSelector,
361422
EnumerableMethod.MinDecimalWithSelector,
362423
EnumerableMethod.MinDoubleWithSelector,
363424
EnumerableMethod.MinInt32WithSelector,
@@ -700,7 +761,6 @@ void DeduceMethodCallSerializers()
700761
case "Atan": DeduceAtanMethodSerializers(); break;
701762
case "Atanh": DeduceAtanhMethodSerializers(); break;
702763
case "Atan2": DeduceAtan2MethodSerializers(); break;
703-
case "Average": DeduceAverageMethodSerializers(); break;
704764
case "CompareTo": DeduceCompareToMethodSerializers(); break;
705765
case "Concat": DeduceConcatMethodSerializers(); break;
706766
case "Constant": DeduceConstantMethodSerializers(); break;
@@ -725,7 +785,6 @@ void DeduceMethodCallSerializers()
725785
case "Inject": DeduceInjectMethodSerializers(); break;
726786
case "Intersect": DeduceIntersectMethodSerializers(); break;
727787
case "IsMatch": DeduceIsMatchMethodSerializers(); break;
728-
case "IsNullOrEmpty": DeduceIsNullOrEmptyMethodSerializers(); break;
729788
case "IsSubsetOf": DeduceIsSubsetOfMethodSerializers(); break;
730789
case "Join": DeduceJoinMethodSerializers(); break;
731790
case "Lookup": DeduceLookupMethodSerializers(); break;
@@ -770,6 +829,12 @@ void DeduceMethodCallSerializers()
770829
DeduceAppendOrPrependMethodSerializers();
771830
break;
772831

832+
case "Average":
833+
case "Median":
834+
case "Percentile":
835+
DeduceAverageOrMedianOrPercentileMethodSerializers();
836+
break;
837+
773838
case "Bottom":
774839
case "BottomN":
775840
case "FirstN":
@@ -820,6 +885,11 @@ void DeduceMethodCallSerializers()
820885
DeduceIsMissingOrIsNullOrMissingMethodSerializers();
821886
break;
822887

888+
case "IsNullOrEmpty":
889+
case "IsNullOrWhiteSpace":
890+
DeduceIsNullOrEmptyOrIsNullOrWhiteSpaceMethodSerializers();
891+
break;
892+
823893
case "Ln":
824894
case "Log":
825895
case "Log10":
@@ -1295,11 +1365,11 @@ void DeduceAtan2MethodSerializers()
12951365
}
12961366
}
12971367

1298-
void DeduceAverageMethodSerializers()
1368+
void DeduceAverageOrMedianOrPercentileMethodSerializers()
12991369
{
1300-
if (method.IsOneOf(__averageMethods))
1370+
if (method.IsOneOf(__averageOrMedianOrPercentileMethods))
13011371
{
1302-
if (method.IsOneOf(__averageWithSelectorMethods))
1372+
if (method.IsOneOf(__averageOrMedianOrPercentileWithSelectorMethods))
13031373
{
13041374
var sourceExpression = arguments[0];
13051375
var selectorLambda = ExpressionHelper.UnquoteLambdaIfQueryableMethod(method, arguments[1]);
@@ -1308,7 +1378,11 @@ void DeduceAverageMethodSerializers()
13081378
DeduceItemAndCollectionSerializers(selectorSourceItemParameter, sourceExpression);
13091379
}
13101380

1311-
DeduceReturnsNumericOrNullableNumericSerializer();
1381+
if (IsNotKnown(node))
1382+
{
1383+
var nodeSerializer = StandardSerializers.GetSerializer(node.Type);
1384+
AddKnownSerializer(node, nodeSerializer);
1385+
}
13121386
}
13131387
else
13141388
{
@@ -2090,9 +2164,9 @@ void DeduceJoinMethodSerializers()
20902164
}
20912165
}
20922166

2093-
void DeduceIsNullOrEmptyMethodSerializers()
2167+
void DeduceIsNullOrEmptyOrIsNullOrWhiteSpaceMethodSerializers()
20942168
{
2095-
if (method.Is(StringMethod.IsNullOrEmpty))
2169+
if (method.IsOneOf(StringMethod.IsNullOrEmpty, StringMethod.IsNullOrWhiteSpace))
20962170
{
20972171
DeduceReturnsBooleanSerializer();
20982172
}
@@ -2619,7 +2693,7 @@ void DeduceReturnsSingleSerializer()
26192693
{
26202694
if (IsNotKnown(node))
26212695
{
2622-
AddKnownSerializer(node, DoubleSerializer.Instance);
2696+
AddKnownSerializer(node, SingleSerializer.Instance);
26232697
}
26242698
}
26252699

tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionTranslators/ModuloComparisonExpressionToFilterTranslatorTests.cs

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ public class ModuloComparisonExpressionToFilterTranslatorTests
3131
[Fact]
3232
public void Translate_should_return_expected_result_with_byte_arguments()
3333
{
34-
var (parameter, expression) = CreateExpression((C c) => c.Byte % 2 == 1);
35-
var context = CreateContext(parameter);
34+
var (lambdaExpression, expression) = CreateExpression((C c) => c.Byte % 2 == 1);
35+
var context = CreateContext(lambdaExpression);
3636
var canTranslate = ModuloComparisonExpressionToFilterTranslator.CanTranslate(expression.Left, expression.Right, out var moduloExpression, out var remainderExpression);
3737
canTranslate.Should().BeTrue();
3838

@@ -44,8 +44,8 @@ public void Translate_should_return_expected_result_with_byte_arguments()
4444
[Fact]
4545
public void Translate_should_return_expected_result_with_decimal_arguments()
4646
{
47-
var (parameter, expression) = CreateExpression((C c) => c.Decimal % 2 == 1);
48-
var context = CreateContext(parameter);
47+
var (lambdaExpression, expression) = CreateExpression((C c) => c.Decimal % 2 == 1);
48+
var context = CreateContext(lambdaExpression);
4949
var canTranslate = ModuloComparisonExpressionToFilterTranslator.CanTranslate(expression.Left, expression.Right, out var moduloExpression, out var remainderExpression);
5050
canTranslate.Should().BeTrue();
5151

@@ -57,8 +57,8 @@ public void Translate_should_return_expected_result_with_decimal_arguments()
5757
[Fact]
5858
public void Translate_should_return_expected_result_with_double_arguments()
5959
{
60-
var (parameter, expression) = CreateExpression((C c) => c.Double % 2 == 1);
61-
var context = CreateContext(parameter);
60+
var (lambdaExpression, expression) = CreateExpression((C c) => c.Double % 2 == 1);
61+
var context = CreateContext(lambdaExpression);
6262
var canTranslate = ModuloComparisonExpressionToFilterTranslator.CanTranslate(expression.Left, expression.Right, out var moduloExpression, out var remainderExpression);
6363
canTranslate.Should().BeTrue();
6464

@@ -70,8 +70,8 @@ public void Translate_should_return_expected_result_with_double_arguments()
7070
[Fact]
7171
public void Translate_should_return_expected_result_with_float_arguments()
7272
{
73-
var (parameter, expression) = CreateExpression((C c) => c.Float % 2 == 1);
74-
var context = CreateContext(parameter);
73+
var (lambdaExpression, expression) = CreateExpression((C c) => c.Float % 2 == 1);
74+
var context = CreateContext(lambdaExpression);
7575
var canTranslate = ModuloComparisonExpressionToFilterTranslator.CanTranslate(expression.Left, expression.Right, out var moduloExpression, out var remainderExpression);
7676
canTranslate.Should().BeTrue();
7777

@@ -83,8 +83,8 @@ public void Translate_should_return_expected_result_with_float_arguments()
8383
[Fact]
8484
public void Translate_should_return_expected_result_with_int16_arguments()
8585
{
86-
var (parameter, expression) = CreateExpression((C c) => c.Int16 % 2 == 1);
87-
var context = CreateContext(parameter);
86+
var (lambdaExpression, expression) = CreateExpression((C c) => c.Int16 % 2 == 1);
87+
var context = CreateContext(lambdaExpression);
8888
var canTranslate = ModuloComparisonExpressionToFilterTranslator.CanTranslate(expression.Left, expression.Right, out var moduloExpression, out var remainderExpression);
8989
canTranslate.Should().BeTrue();
9090

@@ -96,8 +96,8 @@ public void Translate_should_return_expected_result_with_int16_arguments()
9696
[Fact]
9797
public void Translate_should_return_expected_result_with_int32_arguments()
9898
{
99-
var (parameter, expression) = CreateExpression((C c) => c.Int32 % 2 == 1);
100-
var context = CreateContext(parameter);
99+
var (lambdaExpression, expression) = CreateExpression((C c) => c.Int32 % 2 == 1);
100+
var context = CreateContext(lambdaExpression);
101101
var canTranslate = ModuloComparisonExpressionToFilterTranslator.CanTranslate(expression.Left, expression.Right, out var moduloExpression, out var remainderExpression);
102102
canTranslate.Should().BeTrue();
103103

@@ -109,8 +109,8 @@ public void Translate_should_return_expected_result_with_int32_arguments()
109109
[Fact]
110110
public void Translate_should_return_expected_result_with_int64_arguments()
111111
{
112-
var (parameter, expression) = CreateExpression((C c) => c.Int64 % 2 == 1);
113-
var context = CreateContext(parameter);
112+
var (lambdaExpression, expression) = CreateExpression((C c) => c.Int64 % 2 == 1);
113+
var context = CreateContext(lambdaExpression);
114114
var canTranslate = ModuloComparisonExpressionToFilterTranslator.CanTranslate(expression.Left, expression.Right, out var moduloExpression, out var remainderExpression);
115115
canTranslate.Should().BeTrue();
116116

@@ -122,8 +122,8 @@ public void Translate_should_return_expected_result_with_int64_arguments()
122122
[Fact]
123123
public void Translate_should_return_expected_result_with_sbyte_arguments()
124124
{
125-
var (parameter, expression) = CreateExpression((C c) => c.SByte % 2 == 1);
126-
var context = CreateContext(parameter);
125+
var (lambdaExpression, expression) = CreateExpression((C c) => c.SByte % 2 == 1);
126+
var context = CreateContext(lambdaExpression);
127127
var canTranslate = ModuloComparisonExpressionToFilterTranslator.CanTranslate(expression.Left, expression.Right, out var moduloExpression, out var remainderExpression);
128128
canTranslate.Should().BeTrue();
129129

@@ -135,8 +135,8 @@ public void Translate_should_return_expected_result_with_sbyte_arguments()
135135
[Fact]
136136
public void Translate_should_return_expected_result_with_uint16_arguments()
137137
{
138-
var (parameter, expression) = CreateExpression((C c) => c.UInt16 % 2 == 1);
139-
var context = CreateContext(parameter);
138+
var (lambdaExpression, expression) = CreateExpression((C c) => c.UInt16 % 2 == 1);
139+
var context = CreateContext(lambdaExpression);
140140
var canTranslate = ModuloComparisonExpressionToFilterTranslator.CanTranslate(expression.Left, expression.Right, out var moduloExpression, out var remainderExpression);
141141
canTranslate.Should().BeTrue();
142142

@@ -148,8 +148,8 @@ public void Translate_should_return_expected_result_with_uint16_arguments()
148148
[Fact]
149149
public void Translate_should_return_expected_result_with_uint32_arguments()
150150
{
151-
var (parameter, expression) = CreateExpression((C c) => c.UInt32 % 2 == 1);
152-
var context = CreateContext(parameter);
151+
var (lambdaExpression, expression) = CreateExpression((C c) => c.UInt32 % 2 == 1);
152+
var context = CreateContext(lambdaExpression);
153153
var canTranslate = ModuloComparisonExpressionToFilterTranslator.CanTranslate(expression.Left, expression.Right, out var moduloExpression, out var remainderExpression);
154154
canTranslate.Should().BeTrue();
155155

@@ -161,8 +161,8 @@ public void Translate_should_return_expected_result_with_uint32_arguments()
161161
[Fact]
162162
public void Translate_should_return_expected_result_with_uint64_arguments()
163163
{
164-
var (parameter, expression) = CreateExpression((C c) => c.UInt64 % 2 == 1);
165-
var context = CreateContext(parameter);
164+
var (lambdaExpression, expression) = CreateExpression((C c) => c.UInt64 % 2 == 1);
165+
var context = CreateContext(lambdaExpression);
166166
var canTranslate = ModuloComparisonExpressionToFilterTranslator.CanTranslate(expression.Left, expression.Right, out var moduloExpression, out var remainderExpression);
167167
canTranslate.Should().BeTrue();
168168

@@ -180,19 +180,19 @@ private void Assert(AstFilter result, string path, BsonValue divisor, BsonValue
180180
modFilterOperation.Remainder.Should().Be(remainder);
181181
}
182182

183-
private TranslationContext CreateContext(ParameterExpression parameter)
183+
private TranslationContext CreateContext(LambdaExpression lambda)
184184
{
185+
var parameter = lambda.Parameters.Single();
185186
var serializer = BsonSerializer.LookupSerializer(parameter.Type);
186-
var context = TranslationContext.Create(parameter, translationOptions: null);
187+
var context = TranslationContext.Create(lambda, parameter, serializer, translationOptions: null);
187188
var symbol = context.CreateSymbol(parameter, serializer, isCurrent: true);
188189
return context.WithSymbol(symbol);
189190
}
190191

191-
private (ParameterExpression, BinaryExpression) CreateExpression<TField>(Expression<Func<TField, bool>> lambda)
192+
private (LambdaExpression, BinaryExpression) CreateExpression<TField>(Expression<Func<TField, bool>> lambda)
192193
{
193-
var parameter = lambda.Parameters.Single();
194194
var expression = (BinaryExpression)lambda.Body;
195-
return (parameter, expression);
195+
return (lambda, expression);
196196
}
197197

198198
private class C

0 commit comments

Comments
 (0)