Skip to content

Commit a13193a

Browse files
author
rstam
committed
Finished implementing support for LINQ queries against array elements. Added lots more unit tests and made some minor fixes.
1 parent dda21e1 commit a13193a

File tree

2 files changed

+550
-63
lines changed

2 files changed

+550
-63
lines changed

Driver/Linq/Translators/SelectQuery.cs

Lines changed: 41 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ public override object Execute()
130130
foreach (var clause in _orderBy)
131131
{
132132
var memberExpression = (MemberExpression)clause.Key.Body;
133-
var dottedElementName = GetDottedElementName(memberExpression);
133+
var serializationInfo = GetSerializationInfo(memberExpression);
134134
var direction = (clause.Direction == OrderByDirection.Descending) ? -1 : 1;
135-
sortBy.Add(dottedElementName, direction);
135+
sortBy.Add(serializationInfo.ElementName, direction);
136136
}
137137
cursor.SetSortOrder(sortBy);
138138
}
@@ -264,15 +264,15 @@ private IMongoQuery BuildArrayLengthQuery(BinaryExpression binaryExpression)
264264
var valueExpression = binaryExpression.Right as ConstantExpression;
265265
if (memberExpression != null && valueExpression != null)
266266
{
267-
var dottedElementName = GetDottedElementName(memberExpression);
267+
var serializationInfo = GetSerializationInfo(memberExpression);
268268
var value = (int)valueExpression.Value;
269269
if (binaryExpression.NodeType == ExpressionType.Equal)
270270
{
271-
return Query.Size(dottedElementName, value);
271+
return Query.Size(serializationInfo.ElementName, value);
272272
}
273273
else
274274
{
275-
return Query.Not(dottedElementName).Size(value);
275+
return Query.Not(serializationInfo.ElementName).Size(value);
276276
}
277277
}
278278
}
@@ -287,15 +287,15 @@ private IMongoQuery BuildArrayLengthQuery(BinaryExpression binaryExpression)
287287
var valueExpression = binaryExpression.Right as ConstantExpression;
288288
if (memberExpression != null && valueExpression != null)
289289
{
290-
var dottedElementName = GetDottedElementName(memberExpression);
290+
var serializationInfo = GetSerializationInfo(memberExpression);
291291
var value = (int)valueExpression.Value;
292292
if (binaryExpression.NodeType == ExpressionType.Equal)
293293
{
294-
return Query.Size(dottedElementName, value);
294+
return Query.Size(serializationInfo.ElementName, value);
295295
}
296296
else
297297
{
298-
return Query.Not(dottedElementName).Size(value);
298+
return Query.Not(serializationInfo.ElementName).Size(value);
299299
}
300300
}
301301
}
@@ -313,15 +313,15 @@ private IMongoQuery BuildArrayLengthQuery(BinaryExpression binaryExpression)
313313
var valueExpression = binaryExpression.Right as ConstantExpression;
314314
if (memberExpression != null && valueExpression != null)
315315
{
316-
var dottedElementName = GetDottedElementName(memberExpression);
316+
var serializationInfo = GetSerializationInfo(memberExpression);
317317
var value = (int)valueExpression.Value;
318318
if (binaryExpression.NodeType == ExpressionType.Equal)
319319
{
320-
return Query.Size(dottedElementName, value);
320+
return Query.Size(serializationInfo.ElementName, value);
321321
}
322322
else
323323
{
324-
return Query.Not(dottedElementName).Size(value);
324+
return Query.Not(serializationInfo.ElementName).Size(value);
325325
}
326326
}
327327
}
@@ -331,6 +331,19 @@ private IMongoQuery BuildArrayLengthQuery(BinaryExpression binaryExpression)
331331
return null;
332332
}
333333

334+
private IMongoQuery BuildBooleanQuery(Expression expression)
335+
{
336+
if (expression.Type == typeof(bool))
337+
{
338+
var serializationInfo = GetSerializationInfo(expression);
339+
if (serializationInfo != null)
340+
{
341+
return new QueryDocument(serializationInfo.ElementName, true);
342+
}
343+
}
344+
return null;
345+
}
346+
334347
private IMongoQuery BuildComparisonQuery(BinaryExpression binaryExpression)
335348
{
336349
if (binaryExpression.NodeType == ExpressionType.Equal || binaryExpression.NodeType == ExpressionType.NotEqual)
@@ -533,11 +546,10 @@ private IMongoQuery BuildIsMatchQuery(MethodCallExpression methodCallExpression)
533546
{
534547
if (arguments.Length == 2 || arguments.Length == 3)
535548
{
536-
var inputExpression = arguments[0] as MemberExpression;
549+
var serializationInfo = GetSerializationInfo(arguments[0]);
537550
var patternExpression = arguments[1] as ConstantExpression;
538-
if (inputExpression != null && patternExpression != null)
551+
if (serializationInfo != null && patternExpression != null)
539552
{
540-
var dottedElementName = GetDottedElementName(inputExpression);
541553
var pattern = patternExpression.Value as string;
542554
if (pattern != null)
543555
{
@@ -552,7 +564,7 @@ private IMongoQuery BuildIsMatchQuery(MethodCallExpression methodCallExpression)
552564
options = (RegexOptions)optionsExpression.Value;
553565
}
554566
var regex = new Regex(pattern, options);
555-
return Query.Matches(dottedElementName, regex);
567+
return Query.Matches(serializationInfo.ElementName, regex);
556568
}
557569
}
558570
}
@@ -562,29 +574,18 @@ private IMongoQuery BuildIsMatchQuery(MethodCallExpression methodCallExpression)
562574
var regexExpression = obj as ConstantExpression;
563575
if (regexExpression != null && arguments.Length == 1)
564576
{
577+
var serializationInfo = GetSerializationInfo(arguments[0]);
565578
var regex = regexExpression.Value as Regex;
566-
var inputExpression = arguments[0] as MemberExpression;
567-
if (regex != null && inputExpression != null)
579+
if (serializationInfo != null && regex != null)
568580
{
569-
var dottedElementName = GetDottedElementName(inputExpression);
570-
return Query.Matches(dottedElementName, regex);
581+
return Query.Matches(serializationInfo.ElementName, regex);
571582
}
572583
}
573584
}
574585
}
575586
return null;
576587
}
577588

578-
private IMongoQuery BuildMemberQuery(MemberExpression memberExpression)
579-
{
580-
if (memberExpression.Type == typeof(bool))
581-
{
582-
var dottedElementName = GetDottedElementName(memberExpression);
583-
return new QueryDocument(dottedElementName, true);
584-
}
585-
return null;
586-
}
587-
588589
private IMongoQuery BuildMethodCallQuery(MethodCallExpression methodCallExpression)
589590
{
590591
switch (methodCallExpression.Method.Name)
@@ -606,21 +607,20 @@ private IMongoQuery BuildModQuery(BinaryExpression binaryExpression)
606607
var leftBinaryExpression = binaryExpression.Left as BinaryExpression;
607608
if (leftBinaryExpression != null && leftBinaryExpression.NodeType == ExpressionType.Modulo)
608609
{
609-
var memberExpression = leftBinaryExpression.Left as MemberExpression;
610+
var serializationInfo = GetSerializationInfo(leftBinaryExpression.Left);
610611
var modulusExpression = leftBinaryExpression.Right as ConstantExpression;
611612
var equalsExpression = binaryExpression.Right as ConstantExpression;
612-
if (memberExpression != null && modulusExpression != null && equalsExpression != null)
613+
if (serializationInfo != null && modulusExpression != null && equalsExpression != null)
613614
{
614-
var dottedElementName = GetDottedElementName(memberExpression);
615615
var modulus = Convert.ToInt32(modulusExpression.Value);
616616
var equals = Convert.ToInt32(equalsExpression.Value);
617617
if (binaryExpression.NodeType == ExpressionType.Equal)
618618
{
619-
return Query.Mod(dottedElementName, modulus, equals);
619+
return Query.Mod(serializationInfo.ElementName, modulus, equals);
620620
}
621621
else
622622
{
623-
return Query.Not(dottedElementName).Mod(modulus, equals);
623+
return Query.Not(serializationInfo.ElementName).Mod(modulus, equals);
624624
}
625625
}
626626
}
@@ -724,6 +724,9 @@ private IMongoQuery BuildQuery(Expression expression)
724724
case ExpressionType.AndAlso:
725725
query = BuildAndAlsoQuery((BinaryExpression)expression);
726726
break;
727+
case ExpressionType.ArrayIndex:
728+
query = BuildBooleanQuery(expression);
729+
break;
727730
case ExpressionType.Call:
728731
query = BuildMethodCallQuery((MethodCallExpression)expression);
729732
break;
@@ -739,7 +742,7 @@ private IMongoQuery BuildQuery(Expression expression)
739742
query = BuildComparisonQuery((BinaryExpression)expression);
740743
break;
741744
case ExpressionType.MemberAccess:
742-
query = BuildMemberQuery((MemberExpression)expression);
745+
query = BuildBooleanQuery(expression);
743746
break;
744747
case ExpressionType.Not:
745748
query = BuildNotQuery((UnaryExpression)expression);
@@ -770,11 +773,10 @@ private IMongoQuery BuildStringQuery(MethodCallExpression methodCallExpression)
770773
var arguments = methodCallExpression.Arguments.ToArray();
771774
if (arguments.Length == 1)
772775
{
773-
var memberExpression = methodCallExpression.Object as MemberExpression;
776+
var serializationInfo = GetSerializationInfo(methodCallExpression.Object);
774777
var valueExpression = arguments[0] as ConstantExpression;
775-
if (memberExpression != null && valueExpression != null)
778+
if (serializationInfo != null && valueExpression != null)
776779
{
777-
var dottedElementName = GetDottedElementName(memberExpression);
778780
var s = (string)valueExpression.Value;
779781
BsonRegularExpression regex;
780782
switch (methodCallExpression.Method.Name)
@@ -784,7 +786,7 @@ private IMongoQuery BuildStringQuery(MethodCallExpression methodCallExpression)
784786
case "StartsWith": regex = new BsonRegularExpression("^" + s); break;
785787
default: throw new InvalidOperationException("Unreachable code");
786788
}
787-
return Query.Matches(dottedElementName, regex);
789+
return Query.Matches(serializationInfo.ElementName, regex);
788790
}
789791
}
790792
break;
@@ -816,12 +818,6 @@ private void CombinePredicateWithWhereClause(MethodCallExpression methodCallExpr
816818
}
817819
}
818820

819-
private string GetDottedElementName(MemberExpression memberExpression)
820-
{
821-
var serializationInfo = GetSerializationInfo(memberExpression);
822-
return serializationInfo.ElementName;
823-
}
824-
825821
private BsonSerializationInfo GetSerializationInfo(Expression expression)
826822
{
827823
var documentSerializer = BsonSerializer.LookupSerializer(DocumentType);

0 commit comments

Comments
 (0)