From d175be3a1909c0f119eea85d7391286f47e94f3f Mon Sep 17 00:00:00 2001 From: rstam Date: Mon, 13 Jan 2025 18:29:05 -0800 Subject: [PATCH] CSHARP-5321: Change snippet deserialization strategy to remove limitation on number of snippets. --- ...lientSideProjectionSnippetsDeserializer.cs | 127 ++++-------------- .../ClientSideProjectionExpressionRewriter.cs | 33 ++--- .../Jira/CSharp3529Tests.cs | 8 +- .../Jira/CSharp3958Tests.cs | 8 +- .../Jira/CSharp4100ExpressionTests.cs | 32 ++--- .../Jira/CSharp4410Tests.cs | 12 +- .../Jira/CSharp4486Tests.cs | 2 +- .../Jira/CSharp4517Tests.cs | 2 +- .../Jira/CSharp4763Tests.cs | 16 +-- .../Jira/CSharp4813Tests.cs | 6 +- .../Jira/CSharp4957Tests.cs | 2 +- .../Jira/CSharp5043Tests.cs | 4 +- .../Jira/CSharp5321Tests.cs | 4 +- ...nToAggregationExpressionTranslatorTests.cs | 2 +- 14 files changed, 88 insertions(+), 170 deletions(-) diff --git a/src/MongoDB.Driver/ClientSideProjectionSnippetsDeserializer.cs b/src/MongoDB.Driver/ClientSideProjectionSnippetsDeserializer.cs index 5c504a4b599..195fa3ac2cf 100644 --- a/src/MongoDB.Driver/ClientSideProjectionSnippetsDeserializer.cs +++ b/src/MongoDB.Driver/ClientSideProjectionSnippetsDeserializer.cs @@ -24,134 +24,59 @@ namespace MongoDB.Driver { internal static class ClientSideProjectionSnippetsDeserializer { - private static readonly Type[] __deserializerGenericTypeDefinitions = - [ - null, - typeof(ClientSideProjectionSnippetsDeserializer<,>), - typeof(ClientSideProjectionSnippetsDeserializer<,,>), - typeof(ClientSideProjectionSnippetsDeserializer<,,,>), - typeof(ClientSideProjectionSnippetsDeserializer<,,,,>) - ]; - - public const int MaxNumberOfSnippets = 4; // could be expanded up to 16 - public static IBsonSerializer Create( Type projectionType, IBsonSerializer[] snippetDeserializers, Delegate projector) { - var snippetTypes = snippetDeserializers.Select(s => s.ValueType).ToArray(); - var deserializerGenericTypeDefinition = __deserializerGenericTypeDefinitions[snippetTypes.Length]; - var deserializerGenericTypeArguments = snippetTypes.Append(projectionType).ToArray(); - var deserializerType = deserializerGenericTypeDefinition.MakeGenericType(deserializerGenericTypeArguments); + var deserializerType = typeof(ClientSideProjectionSnippetsDeserializer<>).MakeGenericType(projectionType); return (IBsonSerializer)Activator.CreateInstance(deserializerType, [snippetDeserializers, projector]); } } - internal abstract class ClientSideProjectionSnippetsDeserializer : SerializerBase, IClientSideProjectionDeserializer + internal sealed class ClientSideProjectionSnippetsDeserializer : SerializerBase, IClientSideProjectionDeserializer { private readonly IBsonSerializer[] _snippetDeserializers; + private readonly Func _projector; - public ClientSideProjectionSnippetsDeserializer(IBsonSerializer[] snippetDeserializers) + public ClientSideProjectionSnippetsDeserializer(IBsonSerializer[] snippetDeserializers, Func projector) { _snippetDeserializers = snippetDeserializers; + _projector = projector; } - protected object[] DeserializeSnippets(BsonDeserializationContext context) + public override TProjection Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var snippets = DeserializeSnippets(context); + return _projector(snippets); + } + + private object[] DeserializeSnippets(BsonDeserializationContext context) { var reader = context.Reader; - var snippets = new object[_snippetDeserializers.Length]; reader.ReadStartDocument(); + reader.ReadName("_snippets"); + reader.ReadStartArray(); + var snippets = new object[_snippetDeserializers.Length]; + var i = 0; while (reader.ReadBsonType() != BsonType.EndOfDocument) { - var name = reader.ReadName(); - var i = ParseIndex(name); + if (i >= _snippetDeserializers.Length) + { + throw new BsonSerializationException($"Expected {_snippetDeserializers.Length} snippets but found more than that."); + } snippets[i] = _snippetDeserializers[i].Deserialize(context); + i++; } - reader.ReadEndDocument(); - - return snippets; - - int ParseIndex(string name) + if (i != _snippetDeserializers.Length) { - if (name.StartsWith("_") && - int.TryParse(name.Substring(1), out var index) && - index >= 0 && index < _snippetDeserializers.Length) - { - return index; - } - - throw new FormatException("Invalid snippet name: " + name); + throw new BsonSerializationException($"Expected {_snippetDeserializers.Length} snippets but found {i}."); } - } - } - - internal class ClientSideProjectionSnippetsDeserializer : ClientSideProjectionSnippetsDeserializer - { - private readonly Func _projector; - - public ClientSideProjectionSnippetsDeserializer(IBsonSerializer[] snippetDeserializers, Func projector) - : base(snippetDeserializers) - { - _projector = projector; - } - - public override TProjection Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) - { - var snippets = DeserializeSnippets(context); - return _projector((T1)snippets[0]); - } - } - - internal class ClientSideProjectionSnippetsDeserializer : ClientSideProjectionSnippetsDeserializer - { - private readonly Func _projector; - - public ClientSideProjectionSnippetsDeserializer(IBsonSerializer[] snippetDeserializers, Func projector) - : base(snippetDeserializers) - { - _projector = projector; - } - - public override TProjection Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) - { - var snippets = DeserializeSnippets(context); - return _projector((T1)snippets[0], (T2)snippets[1]); - } - } - - internal class ClientSideProjectionSnippetsDeserializer : ClientSideProjectionSnippetsDeserializer - { - private readonly Func _projector; - - public ClientSideProjectionSnippetsDeserializer(IBsonSerializer[] snippetDeserializers, Func projector) - : base(snippetDeserializers) - { - _projector = projector; - } - - public override TProjection Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) - { - var snippets = DeserializeSnippets(context); - return _projector((T1)snippets[0], (T2)snippets[1], (T3)snippets[2]); - } - } - - internal class ClientSideProjectionSnippetsDeserializer : ClientSideProjectionSnippetsDeserializer - { - private readonly Func _projector; - - public ClientSideProjectionSnippetsDeserializer(IBsonSerializer[] snippetDeserializers, Func projector) - : base(snippetDeserializers) - { - _projector = projector; - } + reader.ReadEndArray(); + reader.ReadEndDocument(); - public override TProjection Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) - { - var snippets = DeserializeSnippets(context); - return _projector((T1)snippets[0], (T2)snippets[1], (T3)snippets[2], (T4)snippets[3]); + return snippets; } } } diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/ClientSideProjectionExpressionRewriter.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/ClientSideProjectionExpressionRewriter.cs index a0b822cae95..3f73ed99a44 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/ClientSideProjectionExpressionRewriter.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/ClientSideProjectionExpressionRewriter.cs @@ -17,7 +17,6 @@ using System.Linq.Expressions; using MongoDB.Bson.Serialization; using MongoDB.Driver.Core.Misc; -using MongoDB.Driver.Linq.Linq3Implementation.Ast; using MongoDB.Driver.Linq.Linq3Implementation.Ast.Expressions; using MongoDB.Driver.Linq.Linq3Implementation.Ast.Stages; using MongoDB.Driver.Linq.Linq3Implementation.Misc; @@ -43,7 +42,7 @@ public static (AstProjectStage, IBsonSerializer) CreateClientSideProjection( } } - private static (AstExpression, IBsonSerializer) TranslateLambdaBodyUsingSnippets( + private static (AstComputedDocumentExpression, IBsonSerializer) TranslateLambdaBodyUsingSnippets( TranslationContext context, IBsonSerializer sourceSerializer, LambdaExpression projectionLambda) @@ -57,7 +56,7 @@ private static (AstExpression, IBsonSerializer) TranslateLambdaBodyUsingSnippets var snippets = ClientSideProjectionSnippetsTranslator.TranslateSnippets(context, projectionLambda, sourceSerializer); - if (snippets.Length == 0 || snippets.Length > ClientSideProjectionSnippetsDeserializer.MaxNumberOfSnippets || snippets.Any(IsRoot)) + if (snippets.Length == 0 || snippets.Any(IsRoot)) { var clientSideProjectionDeserializer = ClientSideProjectionDeserializer.Create(sourceSerializer, projectionLambda); return (null, clientSideProjectionDeserializer); // project directly off $$ROOT with no snippets @@ -77,34 +76,28 @@ private static (AstExpression, IBsonSerializer) TranslateLambdaBodyUsingSnippets private static AstComputedDocumentExpression CreateSnippetsComputedDocument(AggregationExpression[] snippets) { - var numberOfSnippets = snippets.Length; - var computedFields = new AstComputedField[numberOfSnippets]; + var snippetsArray = AstExpression.ComputedArray(snippets.Select(s => s.Ast)); + var snippetsdField = AstExpression.ComputedField("_snippets", snippetsArray); + return (AstComputedDocumentExpression)AstExpression.ComputedDocument([snippetsdField]); - for (var i = 0; i < numberOfSnippets; i++) - { - var name = $"_{i}"; - var snippet = snippets[i]; - computedFields[i] = AstExpression.ComputedField(name, snippet.Ast); - } - - return (AstComputedDocumentExpression)AstExpression.ComputedDocument(computedFields); } private static LambdaExpression RewriteSelector(LambdaExpression selectorLambda, AggregationExpression[] snippets) { - var numberOfSnippets = snippets.Length; - var snippetParameters = new ParameterExpression[numberOfSnippets]; var rewrittenBody = selectorLambda.Body; + var snippetsParameter = Expression.Parameter(typeof(object[]), "snippets"); - for (var i = 0; i < numberOfSnippets; i++) + for (var i = 0; i < snippets.Length; i++) { var snippet = snippets[i]; - var snippetParameter = Expression.Parameter(snippet.Expression.Type, $"_{i}"); - rewrittenBody = ExpressionReplacer.Replace(rewrittenBody, snippet.Expression, snippetParameter); - snippetParameters[i] = snippetParameter; + var snippetReference = // (T)_snippets[i] + Expression.Convert( + Expression.ArrayIndex(snippetsParameter, Expression.Constant(i)), + snippet.Expression.Type); + rewrittenBody = ExpressionReplacer.Replace(rewrittenBody, snippet.Expression, snippetReference); } - return Expression.Lambda(rewrittenBody, snippetParameters); + return Expression.Lambda(rewrittenBody, snippetsParameter); } } } diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp3529Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp3529Tests.cs index 0555dca2109..28894ef02b6 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp3529Tests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp3529Tests.cs @@ -166,7 +166,7 @@ public void Bottom_without_GroupBy_should_have_helpful_error_message( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$A', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$A'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var exception = Record.Exception(() => queryable.ToList()); @@ -398,7 +398,7 @@ public void BottomN_without_GroupBy_should_have_helpful_error_message( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$A', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$A'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var exception = Record.Exception(() => queryable.ToList()); @@ -1660,7 +1660,7 @@ public void Top_without_GroupBy_should_have_helpful_error_message( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$A', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$A'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var exception = Record.Exception(() => queryable.ToList()); @@ -1892,7 +1892,7 @@ public void TopN_without_GroupBy_should_have_helpful_error_message( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$A', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$A'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var exception = Record.Exception(() => queryable.ToList()); diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp3958Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp3958Tests.cs index c9f9a4e87a4..b629728d726 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp3958Tests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp3958Tests.cs @@ -156,7 +156,7 @@ public void OrderBy_on_entire_object_followed_by_ThenBy_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$Team', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$Team'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var result = queryable.Single(); @@ -187,7 +187,7 @@ public void OrderByDescending_on_entire_object_followed_by_ThenBy_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$Team', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$Team'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var result = queryable.Single(); @@ -218,7 +218,7 @@ public void ThenBy_on_entire_object_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$Team', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$Team'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var result = queryable.Single(); @@ -248,7 +248,7 @@ public void ThenByDescending_on_entire_object_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$Team', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$Team'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var result = queryable.Single(); diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4100ExpressionTests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4100ExpressionTests.cs index dbc585d06cd..db534655441 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4100ExpressionTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4100ExpressionTests.cs @@ -92,7 +92,7 @@ public void Contains_with_string_field_and_char_field_not_represented_as_string_ if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var serializer); - AssertStages(stages, "{ $project : { _0 : '$S', _1 : '$CC', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$S', '$CC'], _id : 0 } }"); serializer.Should().BeAssignableTo(); } else @@ -118,7 +118,7 @@ public void Contains_with_string_constant_and_char_field_not_represented_as_stri if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var serializer); - AssertStages(stages, "{ $project : { _0 : '$CC', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$CC'], _id : 0 } }"); serializer.Should().BeAssignableTo(); } else @@ -212,7 +212,7 @@ public void Contains_with_string_field_and_char_value_not_represented_as_string_ if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$S', _1 : '$CC', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$S', '$CC'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -246,7 +246,7 @@ public void Contains_with_string_constant_and_char_value_not_represented_as_stri if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$CC', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$CC'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -284,7 +284,7 @@ public void Contains_with_string_field_and_char_value_and_invalid_comparisonType if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$S', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$S'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -452,7 +452,7 @@ public void Contains_with_string_field_and_string_value_and_invalid_comparisonTy if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$S', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$S'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -557,7 +557,7 @@ public void EndsWith_with_string_field_and_char_field_not_represented_as_string_ if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$S', _1 : '$CC', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$S', '$CC'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -588,7 +588,7 @@ public void EndsWith_with_string_constant_and_char_field_not_represented_as_stri if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$CC', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$CC'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -724,7 +724,7 @@ public void EndsWith_with_string_field_and_string_value_and_ignoreCase_and_inval if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$S', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$S'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -830,7 +830,7 @@ public void EndsWith_with_string_field_and_string_value_and_invalid_comparisonTy if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$S', _1 : '$T', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$S', '$T'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -866,7 +866,7 @@ public void EndsWith_with_string_constant_and_string_value_and_invalid_compariso if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$T', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$T'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -952,7 +952,7 @@ public void StartsWith_with_string_field_and_char_field_not_represented_as_strin if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$S', _1 : '$CC', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$S', '$CC'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -983,7 +983,7 @@ public void StartsWith_with_string_constant_and_char_field_not_represented_as_st if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$CC', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$CC'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -1119,7 +1119,7 @@ public void StartsWith_with_string_field_and_string_value_and_ignoreCase_and_inv if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$S', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$S'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -1224,7 +1224,7 @@ public void StartsWith_with_string_field_and_string_value_and_invalid_comparison if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$S', _1 : '$T', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$S', '$T'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -1260,7 +1260,7 @@ public void StartsWith_with_string_constant_and_string_value_and_invalid_compari if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$T', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$T'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4410Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4410Tests.cs index 018cd612e1e..3f0e65febf9 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4410Tests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4410Tests.cs @@ -193,7 +193,7 @@ public void Comparison_of_enum_and_enum_with_mismatched_serializers_should_throw if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$E', _1 : '$S', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$E', '$S'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -223,7 +223,7 @@ public void Comparison_of_enum_and_nullable_enum_with_mismatched_serializers_sho if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$E', _1 : '$NS', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$E', '$NS'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -253,7 +253,7 @@ public void Comparison_of_nullable_enum_and_enum_with_mismatched_serializers_sho if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$NE', _1 : '$S', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$NE', '$S'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -283,7 +283,7 @@ public void Comparison_of_nullable_enum_and_nullable_enum_with_mismatched_serial if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$NE', _1 : '$NS', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$NE', '$NS'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -313,7 +313,7 @@ public void Arithmetic_with_enum_represented_as_string_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$S', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$S'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -343,7 +343,7 @@ public void Arithmetic_with_nullable_enum_represented_as_string_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$NS', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$NS'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4486Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4486Tests.cs index fc36e423677..66ec89f4ff4 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4486Tests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4486Tests.cs @@ -116,7 +116,7 @@ public void Xor_with_two_arguments_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$P', _1 : '$Q', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$P', '$Q'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4517Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4517Tests.cs index baea7079822..eb5fb62d23f 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4517Tests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4517Tests.cs @@ -61,7 +61,7 @@ public void Expression_with_comparison_of_different_types_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$_id', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$_id'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4763Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4763Tests.cs index b3f7ce9c91f..b5d7a8aca5f 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4763Tests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4763Tests.cs @@ -51,7 +51,7 @@ public void Find_with_client_side_projection_ToList_should_work( } else { - projection.Should().Be("{ _0 : '$X', _id : 0 }"); + projection.Should().Be("{ _snippets : ['$X'], _id : 0 }"); } projectionSerializer.Should().BeAssignableTo(); @@ -93,7 +93,7 @@ public void Find_with_client_side_projection_First_should_work( } else { - projection.Should().Be("{ _0 : '$X', _id : 0 }"); + projection.Should().Be("{ _snippets : ['$X'], _id : 0 }"); } projectionSerializer.Should().BeAssignableTo(); @@ -135,7 +135,7 @@ public void Find_with_client_side_projection_Single_should_work( } else { - projection.Should().Be("{ _0 : '$X', _id : 0 }"); + projection.Should().Be("{ _snippets : ['$X'], _id : 0 }"); } projectionSerializer.Should().BeAssignableTo(); @@ -176,7 +176,7 @@ public void Aggregate_Project_with_client_side_projection_ToList_should_work( } else { - AssertStages(stages, "{ $project : { _0 : '$X', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$X'], _id : 0 } }"); } outputSerializer.Should().BeAssignableTo(); @@ -217,7 +217,7 @@ public void Aggregate_Project_with_client_side_projection_First_should_work( } else { - AssertStages(stages, "{ $project : { _0 : '$X', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$X'], _id : 0 } }"); } serializer.Should().BeAssignableTo(); @@ -289,7 +289,7 @@ public void Queryable_Select_with_client_side_projection_ToList_should_work( } else { - AssertStages(stages, "{ $project : { _0 : '$X', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$X'], _id : 0 } }"); } outputSerializer.Should().BeAssignableTo(); @@ -330,7 +330,7 @@ public void Queryable_Select_with_client_side_projection_First_should_work( } else { - AssertStages(stages, "{ $project : { _0 : '$X', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$X'], _id : 0 } }"); } outputSerializer.Should().BeAssignableTo(); @@ -401,7 +401,7 @@ public void Queryable_Select_with_client_side_projection_Single_should_work( } else { - AssertStages(stages, "{ $project : { _0 : '$X', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$X'], _id : 0 } }"); } outputSerializer.Should().BeAssignableTo(); diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4813Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4813Tests.cs index 5d8650032cb..43e145b1354 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4813Tests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4813Tests.cs @@ -186,7 +186,7 @@ public void Select_BitArray_Count_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$BitArray', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$BitArray'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -230,7 +230,7 @@ public void Select_Dictionary_Count_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$Dictionary', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$Dictionary'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -289,7 +289,7 @@ public void Select_DictionaryInterface_Count_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$DictionaryInterface', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$DictionaryInterface'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4957Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4957Tests.cs index e5600f9371b..ae8b8c7d7b8 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4957Tests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4957Tests.cs @@ -91,7 +91,7 @@ public void New_array_with_two_items_with_different_serializers_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$X', _1 : '$Y', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$X', '$Y'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var result = queryable.Single(); diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5043Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5043Tests.cs index fd6e20db57e..76762286d81 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5043Tests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5043Tests.cs @@ -180,7 +180,7 @@ public void Convert_ES1_to_E2_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$ES1', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$ES1'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); @@ -224,7 +224,7 @@ public void Convert_ES1_to_nullable_E2_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$ES1', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$ES1'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList(); diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5321Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5321Tests.cs index 236b59a01c2..f06fad4544b 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5321Tests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5321Tests.cs @@ -39,7 +39,7 @@ public void Client_side_projection_should_fetch_only_needed_fields() } else { - AssertStages(stages, "{ $project : { _0 : '$X', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$X'], _id : 0 } }"); } var result = queryable.Single(); @@ -62,7 +62,7 @@ public void Client_side_projection_should_compute_sum_server_side() } else { - AssertStages(stages, "{ $project : { _0 : { $sum : '$A' }, _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : [{ $sum : '$A' }], _id : 0 } }"); } var result = queryable.Single(); diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/NegateExpressionToAggregationExpressionTranslatorTests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/NegateExpressionToAggregationExpressionTranslatorTests.cs index 6f890400745..b7a7683eba7 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/NegateExpressionToAggregationExpressionTranslatorTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/NegateExpressionToAggregationExpressionTranslatorTests.cs @@ -117,7 +117,7 @@ public void Negate_decimal_as_string_should_throw( if (enableClientSideProjections) { var stages = Translate(collection, queryable, out var outputSerializer); - AssertStages(stages, "{ $project : { _0 : '$DecimalAsString', _id : 0 } }"); + AssertStages(stages, "{ $project : { _snippets : ['$DecimalAsString'], _id : 0 } }"); outputSerializer.Should().BeAssignableTo(); var results = queryable.ToList();