Skip to content

Commit 37a88b2

Browse files
committed
CSHARP-6017: Merge LeftJoin translation into JoinMethodToPipelineTranslator
1 parent 7b5f277 commit 37a88b2

3 files changed

Lines changed: 38 additions & 134 deletions

File tree

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/ExpressionToPipelineTranslator.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,8 @@ public static TranslatedPipeline Translate(TranslationContext context, Expressio
5151
case "GroupJoin":
5252
return GroupJoinMethodToPipelineTranslator.Translate(context, methodCallExpression);
5353
case "Join":
54-
return JoinMethodToPipelineTranslator.Translate(context, methodCallExpression);
5554
case "LeftJoin":
56-
return LeftJoinMethodToPipelineTranslator.Translate(context, methodCallExpression);
55+
return JoinMethodToPipelineTranslator.Translate(context, methodCallExpression);
5756
case "Lookup":
5857
return LookupMethodToPipelineTranslator.Translate(context, methodCallExpression);
5958
case "OfType":

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/JoinMethodToPipelineTranslator.cs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2010-present MongoDB Inc.
1+
/* Copyright 2010-present MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -13,6 +13,8 @@
1313
* limitations under the License.
1414
*/
1515

16+
using System.Collections.Generic;
17+
using System.Linq;
1618
using System.Linq.Expressions;
1719
using MongoDB.Bson.Serialization;
1820
using MongoDB.Driver.Linq.Linq3Implementation.Ast;
@@ -34,7 +36,8 @@ public static TranslatedPipeline Translate(TranslationContext context, MethodCal
3436
var method = expression.Method;
3537
var arguments = expression.Arguments;
3638

37-
if (method.Is(QueryableMethod.Join))
39+
var isLeftJoin = method.IsOneOf(MongoQueryableMethod.LeftJoin, QueryableMethod.LeftJoin);
40+
if (isLeftJoin || method.Is(QueryableMethod.Join))
3841
{
3942
var outerExpression = arguments[0];
4043
var innerExpression = arguments[1];
@@ -58,6 +61,11 @@ public static TranslatedPipeline Translate(TranslationContext context, MethodCal
5861
outerSerializer = pipeline.OutputSerializer;
5962
}
6063

64+
if (isLeftJoin)
65+
{
66+
ThrowIfReservedFieldNames(expression, outerSerializer);
67+
}
68+
6169
var wrapOuterStage = AstStage.Project(
6270
AstProject.Set("_outer", outerAst),
6371
AstProject.Exclude("_id"));
@@ -73,7 +81,9 @@ public static TranslatedPipeline Translate(TranslationContext context, MethodCal
7381
foreignField,
7482
@as: "_inner");
7583

76-
var unwindStage = AstStage.Unwind("_inner");
84+
var unwindStage = isLeftJoin
85+
? AstStage.Unwind("_inner", preserveNullAndEmptyArrays: true)
86+
: AstStage.Unwind("_inner");
7787

7888
var outerParameter = resultSelectorLambda.Parameters[0];
7989
var outerField = AstExpression.GetField(AstExpression.RootVar, "_outer");
@@ -97,5 +107,29 @@ public static TranslatedPipeline Translate(TranslationContext context, MethodCal
97107

98108
throw new ExpressionNotSupportedException(expression);
99109
}
110+
111+
private static readonly HashSet<string> __reservedFieldNames = new HashSet<string> { "_outer", "_inner" };
112+
113+
private static void ThrowIfReservedFieldNames(MethodCallExpression expression, IBsonSerializer serializer)
114+
{
115+
if (serializer is not IBsonDocumentSerializer documentSerializer)
116+
return;
117+
118+
var conflicting = new List<string>();
119+
foreach (var member in serializer.ValueType.GetMembers())
120+
{
121+
if (documentSerializer.TryGetMemberSerializationInfo(member.Name, out var info) &&
122+
__reservedFieldNames.Contains(info.ElementName))
123+
{
124+
conflicting.Add(info.ElementName);
125+
}
126+
}
127+
128+
if (conflicting.Count > 0)
129+
{
130+
throw new ExpressionNotSupportedException(expression,
131+
because: $"the outer document type uses reserved field name(s) {string.Join(", ", conflicting.Select(n => $"'{n}'"))} which are used internally by LeftJoin");
132+
}
133+
}
100134
}
101135
}

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToPipelineTranslators/LeftJoinMethodToPipelineTranslator.cs

Lines changed: 0 additions & 129 deletions
This file was deleted.

0 commit comments

Comments
 (0)