diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstExpressionExtensions.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstExpressionExtensions.cs index fc6b95c5ab9..4f604ea50a4 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstExpressionExtensions.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Expressions/AstExpressionExtensions.cs @@ -35,6 +35,9 @@ public static bool IsInt32Constant(this AstExpression expression, out int value) public static bool IsMaxInt32(this AstExpression expression) => expression.IsInt32Constant(out var value) && value == int.MaxValue; + public static bool IsRootVar(this AstExpression expression) + => expression is AstVarExpression varExpression && varExpression.Name == "ROOT" && varExpression.IsCurrent; + public static bool IsZero(this AstExpression expression) => expression is AstConstantExpression constantExpression && constantExpression.Value == 0; } diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Optimizers/AstGroupingPipelineOptimizer.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Optimizers/AstGroupingPipelineOptimizer.cs index bbfd1d5c330..7098f6f4456 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Optimizers/AstGroupingPipelineOptimizer.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Optimizers/AstGroupingPipelineOptimizer.cs @@ -181,8 +181,7 @@ static bool ProjectsRoot(AstProjectStage projectStage) return projectStage.Specifications.Any( specification => specification is AstProjectStageSetFieldSpecification setFieldSpecification && - setFieldSpecification.Value is AstVarExpression varExpression && - varExpression.Name == "ROOT"); + setFieldSpecification.Value.IsRootVar()); } } } @@ -370,14 +369,12 @@ public override AstNode VisitMapExpression(AstMapExpression node) mapInputGetFieldExpression.FieldName is AstConstantExpression mapInputconstantFieldExpression && mapInputconstantFieldExpression.Value.IsString && mapInputconstantFieldExpression.Value.AsString == "_elements" && - mapInputGetFieldExpression.Input is AstVarExpression mapInputGetFieldVarExpression && - mapInputGetFieldVarExpression.Name == "ROOT") + mapInputGetFieldExpression.Input.IsRootVar()) { var rewrittenArg = (AstExpression)AstNodeReplacer.Replace(node.In, (node.As, _element)); var accumulatorExpression = AstExpression.UnaryAccumulator(AstUnaryAccumulatorOperator.Push, rewrittenArg); var accumulatorFieldName = _accumulators.AddAccumulatorExpression(accumulatorExpression); - var root = AstExpression.Var("ROOT", isCurrent: true); - return AstExpression.GetField(root, accumulatorFieldName); + return AstExpression.GetField(AstExpression.RootVar, accumulatorFieldName); } return base.VisitMapExpression(node); @@ -388,8 +385,7 @@ public override AstNode VisitPickExpression(AstPickExpression node) // { $pickOperator : { source : { $getField : { input : "$$ROOT", field : "_elements" } }, as : "x", sortBy : s, selector : f(x) } } // => { __agg0 : { $pickAccumulatorOperator : { sortBy : s, selector : f(x => element) } } } + "$__agg0" if (node.Source is AstGetFieldExpression getFieldExpression && - getFieldExpression.Input is AstVarExpression varExpression && - varExpression.Name == "ROOT" && + getFieldExpression.Input.IsRootVar() && getFieldExpression.FieldName is AstConstantExpression constantFieldNameExpression && constantFieldNameExpression.Value.IsString && constantFieldNameExpression.Value.AsString == "_elements") @@ -398,8 +394,7 @@ getFieldExpression.FieldName is AstConstantExpression constantFieldNameExpressio var rewrittenSelector = (AstExpression)AstNodeReplacer.Replace(node.Selector, (node.As, _element)); var accumulatorExpression = new AstPickAccumulatorExpression(@operator, node.SortBy, rewrittenSelector, node.N); var accumulatorFieldName = _accumulators.AddAccumulatorExpression(accumulatorExpression); - var root = AstExpression.Var("ROOT", isCurrent: true); - return AstExpression.GetField(root, accumulatorFieldName); + return AstExpression.GetField(AstExpression.RootVar, accumulatorFieldName); } return base.VisitPickExpression(node); @@ -407,8 +402,6 @@ getFieldExpression.FieldName is AstConstantExpression constantFieldNameExpressio public override AstNode VisitUnaryExpression(AstUnaryExpression node) { - var root = AstExpression.Var("ROOT", isCurrent: true); - if (TryOptimizeSizeOfElements(out var optimizedExpression)) { return optimizedExpression; @@ -438,7 +431,7 @@ argGetFieldExpression.FieldName is AstConstantExpression constantFieldNameExpres { var accumulatorExpression = AstExpression.UnaryAccumulator(AstUnaryAccumulatorOperator.Sum, 1); var accumulatorFieldName = _accumulators.AddAccumulatorExpression(accumulatorExpression); - optimizedExpression = AstExpression.GetField(root, accumulatorFieldName); + optimizedExpression = AstExpression.GetField(AstExpression.RootVar, accumulatorFieldName); return true; } } @@ -455,12 +448,11 @@ node.Arg is AstGetFieldExpression getFieldExpression && getFieldExpression.FieldName is AstConstantExpression getFieldConstantFieldNameExpression && getFieldConstantFieldNameExpression.Value.IsString && getFieldConstantFieldNameExpression.Value == "_elements" && - getFieldExpression.Input is AstVarExpression getFieldInputVarExpression && - getFieldInputVarExpression.Name == "ROOT") + getFieldExpression.Input.IsRootVar()) { var accumulatorExpression = AstExpression.UnaryAccumulator(accumulatorOperator, _element); var accumulatorFieldName = _accumulators.AddAccumulatorExpression(accumulatorExpression); - optimizedExpression = AstExpression.GetField(root, accumulatorFieldName); + optimizedExpression = AstExpression.GetField(AstExpression.RootVar, accumulatorFieldName); return true; } @@ -478,13 +470,12 @@ mapExpression.Input is AstGetFieldExpression mapInputGetFieldExpression && mapInputGetFieldExpression.FieldName is AstConstantExpression mapInputconstantFieldExpression && mapInputconstantFieldExpression.Value.IsString && mapInputconstantFieldExpression.Value.AsString == "_elements" && - mapInputGetFieldExpression.Input is AstVarExpression mapInputGetFieldVarExpression && - mapInputGetFieldVarExpression.Name == "ROOT") + mapInputGetFieldExpression.Input.IsRootVar()) { var rewrittenArg = (AstExpression)AstNodeReplacer.Replace(mapExpression.In, (mapExpression.As, _element)); var accumulatorExpression = AstExpression.UnaryAccumulator(accumulatorOperator, rewrittenArg); var accumulatorFieldName = _accumulators.AddAccumulatorExpression(accumulatorExpression); - optimizedExpression = AstExpression.GetField(root, accumulatorFieldName); + optimizedExpression = AstExpression.GetField(AstExpression.RootVar, accumulatorFieldName); return true; } diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/GroupingWithOutputExpressionStageDefinitions.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/GroupingWithOutputExpressionStageDefinitions.cs index 1e40aa1347f..013b9bc4815 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/GroupingWithOutputExpressionStageDefinitions.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/GroupingWithOutputExpressionStageDefinitions.cs @@ -112,7 +112,7 @@ protected override AstStage RenderGroupingStage( var valueSerializer = (IBsonSerializer)groupByTranslation.Serializer; var serializedBoundaries = SerializationHelper.SerializeValues(valueSerializer, _boundaries); var serializedDefault = _options != null && _options.DefaultBucket.HasValue ? SerializationHelper.SerializeValue(valueSerializer, _options.DefaultBucket.Value) : null; - var pushElements = AstExpression.AccumulatorField("_elements", AstUnaryAccumulatorOperator.Push, AstExpression.Var("ROOT", isCurrent: true)); + var pushElements = AstExpression.AccumulatorField("_elements", AstUnaryAccumulatorOperator.Push, AstExpression.RootVar); groupingOutputSerializer = IGroupingSerializer.Create(valueSerializer, inputSerializer); return AstStage.Bucket( @@ -156,7 +156,7 @@ protected override AstStage RenderGroupingStage( var valueSerializer = (IBsonSerializer)groupByTranslation.Serializer; var keySerializer = AggregateBucketAutoResultIdSerializer.Create(valueSerializer); var serializedGranularity = _options != null && _options.Granularity.HasValue ? _options.Granularity.Value.Value : null; - var pushElements = AstExpression.AccumulatorField("_elements", AstUnaryAccumulatorOperator.Push, AstExpression.Var("ROOT", isCurrent: true)); + var pushElements = AstExpression.AccumulatorField("_elements", AstUnaryAccumulatorOperator.Push, AstExpression.RootVar); groupingOutputSerializer = IGroupingSerializer.Create(keySerializer, inputSerializer); return AstStage.BucketAuto( @@ -190,7 +190,7 @@ protected override AstStage RenderGroupingStage( var partiallyEvaluatedGroupBy = (Expression>)PartialEvaluator.EvaluatePartially(_groupBy); var context = TranslationContext.Create(partiallyEvaluatedGroupBy, translationOptions); var groupByTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, partiallyEvaluatedGroupBy, inputSerializer, asRoot: true); - var pushElements = AstExpression.AccumulatorField("_elements", AstUnaryAccumulatorOperator.Push, AstExpression.Var("ROOT", isCurrent: true)); + var pushElements = AstExpression.AccumulatorField("_elements", AstUnaryAccumulatorOperator.Push, AstExpression.RootVar); var groupBySerializer = (IBsonSerializer)groupByTranslation.Serializer; groupingOutputSerializer = IGroupingSerializer.Create(groupBySerializer, inputSerializer); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/LambdaExpressionExtensions.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/LambdaExpressionExtensions.cs index d8229d2537d..e0fb4d9efbb 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/LambdaExpressionExtensions.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/LambdaExpressionExtensions.cs @@ -38,7 +38,7 @@ public static string TranslateToDottedFieldName(this LambdaExpression fieldSelec { throw new ArgumentException($"ValueType '{parameterSerializer.ValueType.FullName}' of parameterSerializer does not match parameter type '{parameterExpression.Type.FullName}'.", nameof(parameterSerializer)); } - var parameterSymbol = context.CreateSymbolWithVarName(parameterExpression, varName: "ROOT", parameterSerializer, isCurrent: true); + var parameterSymbol = context.CreateRootSymbol(parameterExpression, parameterSerializer); var lambdaContext = context.WithSymbol(parameterSymbol); var lambdaBody = ConvertHelper.RemoveConvertToObject(fieldSelectorLambda.Body); var fieldSelectorTranslation = ExpressionToAggregationExpressionTranslator.Translate(lambdaContext, lambdaBody); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/ProjectionHelper.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/ProjectionHelper.cs index 1fe3294712e..b2cc92e8854 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/ProjectionHelper.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/ProjectionHelper.cs @@ -100,7 +100,7 @@ private static (string, IBsonSerializer) CreateGetFieldChainWithSafeFieldNamesPr var wrappedValueSerializer = WrappedValueSerializer.Create(fieldName, serializer); var input = getFieldExpression.Input; - if (input is AstVarExpression varExpression && varExpression.Name == "ROOT") + if (input.IsRootVar()) { return (fieldName, wrappedValueSerializer); } @@ -132,7 +132,7 @@ private static bool IsGetFieldChainWithSafeFieldNames(AstGetFieldExpression getF return getFieldExpression.HasSafeFieldName(out _) && ( - (getFieldExpression.Input is AstVarExpression varExpression && varExpression.Name == "ROOT") || + (getFieldExpression.Input.IsRootVar()) || (getFieldExpression.Input is AstGetFieldExpression nestedGetFieldExpression && IsGetFieldChainWithSafeFieldNames(nestedGetFieldExpression)) ); } diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/ExpressionToAggregationExpressionTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/ExpressionToAggregationExpressionTranslator.cs index 81a4dfc6ae7..abb3ba1766d 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/ExpressionToAggregationExpressionTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/ExpressionToAggregationExpressionTranslator.cs @@ -122,7 +122,7 @@ public static AggregationExpression TranslateLambdaBody( } var parameterSymbol = asRoot ? - context.CreateSymbolWithVarName(parameterExpression, varName: "ROOT", parameterSerializer, isCurrent: true) : + context.CreateRootSymbol(parameterExpression, parameterSerializer) : context.CreateSymbol(parameterExpression, parameterSerializer, isCurrent: false); return TranslateLambdaBody(context, lambdaExpression, parameterSymbol); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/PickMethodToAggregationExpressionTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/PickMethodToAggregationExpressionTranslator.cs index c9271192990..34605be14dd 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/PickMethodToAggregationExpressionTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodTranslators/PickMethodToAggregationExpressionTranslator.cs @@ -260,8 +260,7 @@ private static bool IsGroupingSource(AstExpression source) { return source is AstGetFieldExpression getFieldExpression && - getFieldExpression.Input is AstVarExpression inputVarExpression && - inputVarExpression.Name == "ROOT" && + getFieldExpression.Input.IsRootVar() && getFieldExpression.FieldName is AstConstantExpression fieldNameConstantExpression && fieldNameConstantExpression.Value == "_elements"; } @@ -269,9 +268,8 @@ getFieldExpression.FieldName is AstConstantExpression fieldNameConstantExpressio private static bool IsValidKey(AggregationExpression keyTranslation) { if (keyTranslation.Ast is AstGetFieldExpression getFieldExpression && - getFieldExpression.Input is AstVarExpression inputVarExpression && + getFieldExpression.Input.IsRootVar() && getFieldExpression.FieldName is AstConstantExpression constantFieldName && - inputVarExpression.Name == "ROOT" && constantFieldName.Value == "_id") { return true; diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/AverageMethodToExecutableQueryTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/AverageMethodToExecutableQueryTranslator.cs index 05f81419084..17c6006aef6 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/AverageMethodToExecutableQueryTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/AverageMethodToExecutableQueryTranslator.cs @@ -133,8 +133,7 @@ public static ExecutableQuery Translate(MongoQuer else { Ensure.That(sourceSerializer is IWrappedValueSerializer, "Expected sourceSerializer to be an IWrappedValueSerializer.", nameof(sourceSerializer)); - var root = AstExpression.Var("ROOT", isCurrent: true); - valueExpression = AstExpression.GetField(root, "_v"); + valueExpression = AstExpression.GetField(AstExpression.RootVar, "_v"); } IBsonSerializer outputValueSerializer = expression.GetResultType() switch diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/ContainsMethodToExecutableQueryTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/ContainsMethodToExecutableQueryTranslator.cs index bd941f2972e..9635ae73c00 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/ContainsMethodToExecutableQueryTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/ContainsMethodToExecutableQueryTranslator.cs @@ -63,7 +63,7 @@ public static ExecutableQuery Translate(MongoQueryPr wrappedValueSerializer, AstStage.Project( AstProject.ExcludeId(), - AstProject.Set("_v", AstExpression.Var("ROOT")))); + AstProject.Set("_v", AstExpression.RootVar))); } var itemExpression = arguments[1]; diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/LastMethodToExecutableQueryTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/LastMethodToExecutableQueryTranslator.cs index 509e3f7540c..052a3da9fbf 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/LastMethodToExecutableQueryTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/LastMethodToExecutableQueryTranslator.cs @@ -79,7 +79,7 @@ public static ExecutableQuery Translate(MongoQuer pipeline.OutputSerializer, AstStage.Group( id: BsonNull.Value, - fields: AstExpression.AccumulatorField("_last", AstUnaryAccumulatorOperator.Last, AstExpression.Var("ROOT")))); + fields: AstExpression.AccumulatorField("_last", AstUnaryAccumulatorOperator.Last, AstExpression.RootVar))); var finalizer = method.Name == "LastOrDefault" ? __singleOrDefaultFinalizer : __singleFinalizer; diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/MaxMethodToExecutableQueryTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/MaxMethodToExecutableQueryTranslator.cs index 40300ddacae..e13a1c4669e 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/MaxMethodToExecutableQueryTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/MaxMethodToExecutableQueryTranslator.cs @@ -66,7 +66,6 @@ public static ExecutableQuery Translate(MongoQuer ClientSideProjectionHelper.ThrowIfClientSideProjection(expression, pipeline, method); var sourceSerializer = pipeline.OutputSerializer; - var root = AstExpression.Var("ROOT", isCurrent: true); AstExpression valueAst; IBsonSerializer valueSerializer; if (method.IsOneOf(__maxWithSelectorMethods)) @@ -86,7 +85,7 @@ public static ExecutableQuery Translate(MongoQuer } else { - valueAst = root; + valueAst = AstExpression.RootVar; valueSerializer = pipeline.OutputSerializer; } @@ -95,7 +94,7 @@ public static ExecutableQuery Translate(MongoQuer AstStage.Group( id: BsonNull.Value, fields: AstExpression.AccumulatorField("_max", AstUnaryAccumulatorOperator.Max, valueAst)), - AstStage.ReplaceRoot(AstExpression.GetField(root, "_max"))); + AstStage.ReplaceRoot(AstExpression.GetField(AstExpression.RootVar, "_max"))); return ExecutableQuery.Create( provider, diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/MinMethodToExecutableQueryTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/MinMethodToExecutableQueryTranslator.cs index 60da64d53f6..4c65161c86c 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/MinMethodToExecutableQueryTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/MinMethodToExecutableQueryTranslator.cs @@ -66,7 +66,6 @@ public static ExecutableQuery Translate(MongoQuer ClientSideProjectionHelper.ThrowIfClientSideProjection(expression, pipeline, method); var sourceSerializer = pipeline.OutputSerializer; - var root = AstExpression.Var("ROOT", isCurrent: true); AstExpression valueAst; IBsonSerializer valueSerializer; if (method.IsOneOf(__minWithSelectorMethods)) @@ -86,7 +85,7 @@ public static ExecutableQuery Translate(MongoQuer } else { - valueAst = root; + valueAst = AstExpression.RootVar; valueSerializer = pipeline.OutputSerializer; } @@ -95,7 +94,7 @@ public static ExecutableQuery Translate(MongoQuer AstStage.Group( id: BsonNull.Value, fields: AstExpression.AccumulatorField("_min", AstUnaryAccumulatorOperator.Min, valueAst)), - AstStage.ReplaceRoot(AstExpression.GetField(root, "_min"))); + AstStage.ReplaceRoot(AstExpression.GetField(AstExpression.RootVar, "_min"))); return ExecutableQuery.Create( provider, diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/StandardDeviationMethodToExecutableQueryTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/StandardDeviationMethodToExecutableQueryTranslator.cs index d40c45b14ee..6806ff83ed5 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/StandardDeviationMethodToExecutableQueryTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/StandardDeviationMethodToExecutableQueryTranslator.cs @@ -281,8 +281,7 @@ public static ExecutableQuery Translate(MongoQuer } else { - var root = AstExpression.Var("ROOT", isCurrent: true); - valueAst = AstExpression.GetField(root, "_v"); + valueAst = AstExpression.GetField(AstExpression.RootVar, "_v"); } var outputValueType = expression.GetResultType(); var outputValueSerializer = BsonSerializer.LookupSerializer(outputValueType); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/SumMethodToExecutableQueryTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/SumMethodToExecutableQueryTranslator.cs index 29f9b0efc5c..15c6b8706a5 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/SumMethodToExecutableQueryTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToExecutableQueryTranslators/SumMethodToExecutableQueryTranslator.cs @@ -115,7 +115,7 @@ public static ExecutableQuery Translate(MongoQuer var arguments = expression.Arguments; if (method.IsOneOf(__sumMethods)) - { + { var sourceExpression = arguments[0]; var pipeline = ExpressionToPipelineTranslator.Translate(context, sourceExpression); ClientSideProjectionHelper.ThrowIfClientSideProjection(expression, pipeline, method); @@ -131,8 +131,7 @@ public static ExecutableQuery Translate(MongoQuer else { Ensure.That(sourceSerializer is IWrappedValueSerializer, "Expected sourceSerializer to be an IWrappedValueSerializer.", nameof(sourceSerializer)); - var rootVar = AstExpression.Var("ROOT", isCurrent: true); - valueAst = AstExpression.GetField(rootVar, "_v"); + valueAst = AstExpression.GetField(AstExpression.RootVar, "_v"); } var outputValueType = expression.GetResultType(); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionToFilterTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionToFilterTranslator.cs index 739ba219a42..590bd2f7a48 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionToFilterTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionToFilterTranslator.cs @@ -63,7 +63,7 @@ public static AstFilter TranslateLambda( var parameterSymbol = asRoot ? - context.CreateSymbolWithVarName(parameterExpression, varName: "ROOT", parameterSerializer, isCurrent: true) : + context.CreateRootSymbol(parameterExpression, parameterSerializer) : context.CreateSymbol(parameterExpression, parameterSerializer, isCurrent: true); var lambdaContext = context.WithSymbol(parameterSymbol); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/DistinctMethodToPipelineTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/DistinctMethodToPipelineTranslator.cs index 47fff243bdb..a2b99ce1cef 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/DistinctMethodToPipelineTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/DistinctMethodToPipelineTranslator.cs @@ -37,12 +37,10 @@ public static TranslatedPipeline Translate(TranslationContext context, MethodCal var pipeline = ExpressionToPipelineTranslator.Translate(context, sourceExpression); ClientSideProjectionHelper.ThrowIfClientSideProjection(expression, pipeline, method); - var rootVar = AstExpression.Var("ROOT", isCurrent: true); - pipeline = pipeline.AddStages( pipeline.OutputSerializer, - AstStage.Group(rootVar, Enumerable.Empty()), - AstStage.ReplaceRoot(AstExpression.GetField(rootVar, "_id"))); + AstStage.Group(AstExpression.RootVar, Enumerable.Empty()), + AstStage.ReplaceRoot(AstExpression.GetField(AstExpression.RootVar, "_id"))); return pipeline; } diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/GroupByMethodToPipelineTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/GroupByMethodToPipelineTranslator.cs index 3ba59ce82c9..c6ea935f723 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/GroupByMethodToPipelineTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/GroupByMethodToPipelineTranslator.cs @@ -113,16 +113,14 @@ private static (AstExpression, IBsonSerializer) TranslateElement( } else { - var rootVar = AstExpression.Var("ROOT", isCurrent: true); - if (sourceSerializer is IWrappedValueSerializer wrappedSerializer) { - elementAst = AstExpression.GetField(rootVar, wrappedSerializer.FieldName); + elementAst = AstExpression.GetField(AstExpression.RootVar, wrappedSerializer.FieldName); elementSerializer = wrappedSerializer.ValueSerializer; } else { - elementAst = rootVar; + elementAst = AstExpression.RootVar; elementSerializer = sourceSerializer; } } @@ -138,12 +136,11 @@ private static TranslatedPipeline TranslateResultSelector( IBsonSerializer elementSerializer) { var resultSelectorLambda = ExpressionHelper.UnquoteLambda(arguments.Last()); - var root = AstExpression.Var("ROOT", isCurrent: true); var keyParameter = resultSelectorLambda.Parameters[0]; - var keyField = AstExpression.GetField(root, "_id"); + var keyField = AstExpression.GetField(AstExpression.RootVar, "_id"); var keySymbol = context.CreateSymbol(keyParameter, keyField, keySerializer); var elementsParameter = resultSelectorLambda.Parameters[1]; - var elementsField = AstExpression.GetField(root, "_elements"); + var elementsField = AstExpression.GetField(AstExpression.RootVar, "_elements"); var elementsSerializer = IEnumerableSerializer.Create(elementSerializer); var elementsSymbol = context.CreateSymbol(elementsParameter, elementsField, elementsSerializer); var resultSelectContext = context.WithSymbols(keySymbol, elementsSymbol); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/OrderByMethodToPipelineTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/OrderByMethodToPipelineTranslator.cs index 1faaaffe242..008c794a817 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/OrderByMethodToPipelineTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/OrderByMethodToPipelineTranslator.cs @@ -224,7 +224,7 @@ private static AstStage[] CreateSortStages(string methodName, AggregationExpress { var projectStage = AstStage.Project( AstProject.Exclude("_id"), - AstProject.Set("_document", AstExpression.Var("ROOT")), + AstProject.Set("_document", AstExpression.RootVar), AstProject.Set("_key1", keySelectorTranslation.Ast)); var sortStage = AstStage.Sort(AstSort.Field("_key1", sortOrder)); var replaceRootStage = AstStage.ReplaceRoot(AstExpression.FieldPath("$_document")); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/SelectManyMethodToPipelineTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/SelectManyMethodToPipelineTranslator.cs index 89aa3547c12..08eeb62b7ac 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/SelectManyMethodToPipelineTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/SelectManyMethodToPipelineTranslator.cs @@ -136,7 +136,7 @@ private static TranslatedPipeline TranslateSelectManyWithCollectionSelectorAndNo var collectionItemSerializer = ArraySerializerHelper.GetItemSerializer(collectionSelectorTranslation.Serializer); var resultSelectorSourceParameterExpression = resultSelectorLambda.Parameters[0]; - var resultSelectorSourceAst = AstExpression.Var("ROOT", isCurrent: true); + var resultSelectorSourceAst = AstExpression.RootVar; var resultSelectorSourceParameterSymbol = context.CreateSymbol(resultSelectorSourceParameterExpression, resultSelectorSourceAst, sourceSerializer, isCurrent: true); var resultSelectorCollectionItemParameterExpression = resultSelectorLambda.Parameters[1]; var resultSelectorCollectionItemParameterSymbol = context.CreateSymbol(resultSelectorCollectionItemParameterExpression, collectionItemSerializer); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/TranslationContext.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/TranslationContext.cs index 55629aac049..74026b826be 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/TranslationContext.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/TranslationContext.cs @@ -61,6 +61,11 @@ private TranslationContext( public ExpressionTranslationOptions TranslationOptions => _translationOptions; // public methods + public Symbol CreateRootSymbol(ParameterExpression parameter, IBsonSerializer serializer) + { + return CreateSymbolWithVarName(parameter, varName: "ROOT", serializer, isCurrent: true); + } + public Symbol CreateSymbol(ParameterExpression parameter, IBsonSerializer serializer, bool isCurrent = false) { var parameterName = _nameGenerator.GetParameterName(parameter); diff --git a/src/MongoDB.Driver/Linq/LinqProviderAdapter.cs b/src/MongoDB.Driver/Linq/LinqProviderAdapter.cs index 69c7cd21b8c..d0c1eb8a21b 100644 --- a/src/MongoDB.Driver/Linq/LinqProviderAdapter.cs +++ b/src/MongoDB.Driver/Linq/LinqProviderAdapter.cs @@ -202,7 +202,7 @@ internal static BsonDocument TranslateExpressionToSetStage( { var context = TranslationContext.Create(expression, translationOptions); // do not partially evaluate expression var parameter = expression.Parameters.Single(); - var symbol = context.CreateSymbolWithVarName(parameter, varName: "ROOT", documentSerializer, isCurrent: true); + var symbol = context.CreateRootSymbol(parameter, documentSerializer); context = context.WithSymbol(symbol); var setStage = ExpressionToSetStageTranslator.Translate(context, documentSerializer, expression); var simplifiedSetStage = AstSimplifier.SimplifyAndConvert(setStage);