Skip to content

Commit

Permalink
CSHARP-5180: Support additional numeric conversions involving Nullabl…
Browse files Browse the repository at this point in the history
…e<T>.
  • Loading branch information
rstam committed Jul 16, 2024
1 parent 0c5c09e commit ce1a394
Show file tree
Hide file tree
Showing 4 changed files with 1,814 additions and 176 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
using MongoDB.Bson;
using MongoDB.Driver.Linq.Linq3Implementation.Ast.Expressions;
using MongoDB.Driver.Linq.Linq3Implementation.Ast.Filters;
using MongoDB.Driver.Linq.Linq3Implementation.Ast.Stages;
using MongoDB.Driver.Linq.Linq3Implementation.Ast.Visitors;

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

public override AstNode VisitCondExpression(AstCondExpression node)
{
// { $cond : [{ $eq : [expr1, null] }, null, expr2] }
if (node.If is AstBinaryExpression binaryIfpression &&
binaryIfpression.Operator == AstBinaryOperator.Eq &&
binaryIfpression.Arg1 is AstExpression expr1 &&
binaryIfpression.Arg2 is AstConstantExpression constantComparandExpression &&
constantComparandExpression.Value == BsonNull.Value &&
node.Then is AstConstantExpression constantThenExpression &&
constantThenExpression.Value == BsonNull.Value &&
node.Else is AstExpression expr2)
{
// { $cond : [{ $eq : [expr, null] }, null, expr] } => expr
if (expr1 == expr2)
{
return Visit(expr2);
}

// { $cond : [{ $eq : [expr, null] }, null, { $toT : expr }] } => { $toT : expr } for operators that map null to null
if (expr2 is AstUnaryExpression unaryElseExpression &&
OperatorMapsNullToNull(unaryElseExpression.Operator) &&
unaryElseExpression.Arg == expr1)
{
return Visit(expr2);
}
}

return base.VisitCondExpression(node);

static bool OperatorMapsNullToNull(AstUnaryOperator @operator)
{
return @operator switch
{
AstUnaryOperator.ToDecimal => true,
AstUnaryOperator.ToDouble => true,
AstUnaryOperator.ToInt => true,
AstUnaryOperator.ToLong => true,
_ => false
};
}
}

public override AstNode VisitFieldOperationFilter(AstFieldOperationFilter node)
{
node = (AstFieldOperationFilter)base.VisitFieldOperationFilter(node);
Expand Down Expand Up @@ -281,6 +322,22 @@ bool TrySimplifyAsLet(AstGetFieldExpression node, out AstExpression simplified)
}
}

public override AstNode VisitLetExpression(AstLetExpression node)
{
node = (AstLetExpression)base.VisitLetExpression(node);

// { $let : { vars : { var : expr }, in : "$$var" } } => expr
if (node.Vars.Count == 1 &&
node.Vars[0].Var.Name is string varName &&
node.In is AstVarExpression varExpression &&
varExpression.Name == varName)
{
return node.Vars[0].Value;
}

return node;
}

public override AstNode VisitMapExpression(AstMapExpression node)
{
// { $map : { input : <input>, as : "v", in : "$$v.x" } } => { $getField : { field : "x", input : <input> } }
Expand Down
Loading

0 comments on commit ce1a394

Please sign in to comment.