Skip to content

Commit ce1a394

Browse files
committed
CSHARP-5180: Support additional numeric conversions involving Nullable<T>.
1 parent 0c5c09e commit ce1a394

File tree

4 files changed

+1814
-176
lines changed

4 files changed

+1814
-176
lines changed

src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Optimizers/AstSimplifier.cs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
using MongoDB.Bson;
1717
using MongoDB.Driver.Linq.Linq3Implementation.Ast.Expressions;
1818
using MongoDB.Driver.Linq.Linq3Implementation.Ast.Filters;
19-
using MongoDB.Driver.Linq.Linq3Implementation.Ast.Stages;
2019
using MongoDB.Driver.Linq.Linq3Implementation.Ast.Visitors;
2120

2221
namespace MongoDB.Driver.Linq.Linq3Implementation.Ast.Optimizers
@@ -37,6 +36,48 @@ public static TNode SimplifyAndConvert<TNode>(TNode node)
3736
}
3837
#endregion
3938

39+
public override AstNode VisitCondExpression(AstCondExpression node)
40+
{
41+
// { $cond : [{ $eq : [expr1, null] }, null, expr2] }
42+
if (node.If is AstBinaryExpression binaryIfpression &&
43+
binaryIfpression.Operator == AstBinaryOperator.Eq &&
44+
binaryIfpression.Arg1 is AstExpression expr1 &&
45+
binaryIfpression.Arg2 is AstConstantExpression constantComparandExpression &&
46+
constantComparandExpression.Value == BsonNull.Value &&
47+
node.Then is AstConstantExpression constantThenExpression &&
48+
constantThenExpression.Value == BsonNull.Value &&
49+
node.Else is AstExpression expr2)
50+
{
51+
// { $cond : [{ $eq : [expr, null] }, null, expr] } => expr
52+
if (expr1 == expr2)
53+
{
54+
return Visit(expr2);
55+
}
56+
57+
// { $cond : [{ $eq : [expr, null] }, null, { $toT : expr }] } => { $toT : expr } for operators that map null to null
58+
if (expr2 is AstUnaryExpression unaryElseExpression &&
59+
OperatorMapsNullToNull(unaryElseExpression.Operator) &&
60+
unaryElseExpression.Arg == expr1)
61+
{
62+
return Visit(expr2);
63+
}
64+
}
65+
66+
return base.VisitCondExpression(node);
67+
68+
static bool OperatorMapsNullToNull(AstUnaryOperator @operator)
69+
{
70+
return @operator switch
71+
{
72+
AstUnaryOperator.ToDecimal => true,
73+
AstUnaryOperator.ToDouble => true,
74+
AstUnaryOperator.ToInt => true,
75+
AstUnaryOperator.ToLong => true,
76+
_ => false
77+
};
78+
}
79+
}
80+
4081
public override AstNode VisitFieldOperationFilter(AstFieldOperationFilter node)
4182
{
4283
node = (AstFieldOperationFilter)base.VisitFieldOperationFilter(node);
@@ -281,6 +322,22 @@ bool TrySimplifyAsLet(AstGetFieldExpression node, out AstExpression simplified)
281322
}
282323
}
283324

325+
public override AstNode VisitLetExpression(AstLetExpression node)
326+
{
327+
node = (AstLetExpression)base.VisitLetExpression(node);
328+
329+
// { $let : { vars : { var : expr }, in : "$$var" } } => expr
330+
if (node.Vars.Count == 1 &&
331+
node.Vars[0].Var.Name is string varName &&
332+
node.In is AstVarExpression varExpression &&
333+
varExpression.Name == varName)
334+
{
335+
return node.Vars[0].Value;
336+
}
337+
338+
return node;
339+
}
340+
284341
public override AstNode VisitMapExpression(AstMapExpression node)
285342
{
286343
// { $map : { input : <input>, as : "v", in : "$$v.x" } } => { $getField : { field : "x", input : <input> } }

0 commit comments

Comments
 (0)