Skip to content

Commit 7c8a043

Browse files
author
rstam
committed
Added some more unit tests for the Distinct LINQ query operator and for LINQ queries against list elements (as opposed to array elements) and fixed some minor issues discovered as a result.
1 parent ddc5823 commit 7c8a043

File tree

3 files changed

+296
-1
lines changed

3 files changed

+296
-1
lines changed

Driver/Linq/Expressions/ExpressionPrettyPrinter.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,15 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
260260
using (new Indentation(this))
261261
{
262262
WriteLine("Method={0}", node.Method.Name);
263+
if (node.Object == null)
264+
{
265+
WriteLine("Object=null");
266+
}
267+
else
268+
{
269+
WriteLine("Object:");
270+
VisitIndented(node.Object);
271+
}
263272
WriteLine("Arguments:");
264273
using (new Indentation(this))
265274
{

Driver/Linq/Translators/SelectQuery.cs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,12 @@ private BsonSerializationInfo GetSerializationInfo(IBsonSerializer serializer, E
878878
return GetSerializationInfoArrayIndex(serializer, binaryExpression);
879879
}
880880

881+
var methodCallExpression = expression as MethodCallExpression;
882+
if (methodCallExpression != null && methodCallExpression.Method.Name == "get_Item")
883+
{
884+
return GetSerializationInfoGetItem(serializer, methodCallExpression);
885+
}
886+
881887
return null;
882888
}
883889

@@ -902,6 +908,31 @@ private BsonSerializationInfo GetSerializationInfoArrayIndex(IBsonSerializer ser
902908
return null;
903909
}
904910

911+
private BsonSerializationInfo GetSerializationInfoGetItem(IBsonSerializer serializer, MethodCallExpression methodCallExpression)
912+
{
913+
var arguments = methodCallExpression.Arguments.ToArray();
914+
if (arguments.Length == 1)
915+
{
916+
var arraySerializationInfo = GetSerializationInfo(serializer, methodCallExpression.Object);
917+
if (arraySerializationInfo != null)
918+
{
919+
var itemSerializationInfo = arraySerializationInfo.Serializer.GetItemSerializationInfo();
920+
var indexEpression = arguments[0] as ConstantExpression;
921+
if (indexEpression != null)
922+
{
923+
var index = Convert.ToInt32(indexEpression.Value);
924+
return new BsonSerializationInfo(
925+
arraySerializationInfo.ElementName + "." + index.ToString(),
926+
itemSerializationInfo.Serializer,
927+
itemSerializationInfo.NominalType,
928+
itemSerializationInfo.SerializationOptions);
929+
}
930+
}
931+
}
932+
933+
return null;
934+
}
935+
905936
private BsonSerializationInfo GetSerializationInfoMember(IBsonSerializer serializer, MemberExpression memberExpression)
906937
{
907938
var declaringType = memberExpression.Expression.Type;
@@ -1063,7 +1094,6 @@ private void TranslateDistinct(MethodCallExpression methodCallExpression)
10631094
throw new InvalidOperationException(message);
10641095
}
10651096

1066-
Translate(arguments[0]);
10671097
_distinct = true;
10681098
}
10691099

DriverOnlineTests/Linq/SelectQueryTests.cs

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,16 @@ public void TestDefaultIfEmptyWithDefaultValue()
374374
query.ToList(); // execute query
375375
}
376376

377+
[Test]
378+
public void TestDistinctASub0()
379+
{
380+
var query = (from c in _collection.AsQueryable<C>()
381+
select c.A[0]).Distinct();
382+
var results = query.ToList();
383+
Assert.AreEqual(1, results.Count);
384+
Assert.IsTrue(results.Contains(2));
385+
}
386+
377387
[Test]
378388
public void TestDistinctB()
379389
{
@@ -385,6 +395,16 @@ public void TestDistinctB()
385395
Assert.IsTrue(results.Contains(true));
386396
}
387397

398+
[Test]
399+
public void TestDistinctBASub0()
400+
{
401+
var query = (from c in _collection.AsQueryable<C>()
402+
select c.BA[0]).Distinct();
403+
var results = query.ToList();
404+
Assert.AreEqual(1, results.Count);
405+
Assert.IsTrue(results.Contains(true));
406+
}
407+
388408
[Test]
389409
public void TestDistinctD()
390410
{
@@ -409,6 +429,16 @@ public void TestDistinctDBRef()
409429
Assert.IsTrue(results.Contains(new MongoDBRef("db", "c", 1)));
410430
}
411431

432+
[Test]
433+
public void TestDistinctDBRefDatabase()
434+
{
435+
var query = (from c in _collection.AsQueryable<C>()
436+
select c.DBRef.DatabaseName).Distinct();
437+
var results = query.ToList();
438+
Assert.AreEqual(1, results.Count);
439+
Assert.IsTrue(results.Contains("db"));
440+
}
441+
412442
[Test]
413443
public void TestDistinctDZ()
414444
{
@@ -433,6 +463,16 @@ public void TestDistinctE()
433463
Assert.IsTrue(results.Contains(E.A));
434464
}
435465

466+
[Test]
467+
public void TestDistinctEASub0()
468+
{
469+
var query = (from c in _collection.AsQueryable<C>()
470+
select c.EA[0]).Distinct();
471+
var results = query.ToList();
472+
Assert.AreEqual(1, results.Count);
473+
Assert.IsTrue(results.Contains(E.A));
474+
}
475+
436476
[Test]
437477
public void TestDistinctId()
438478
{
@@ -447,6 +487,16 @@ public void TestDistinctId()
447487
Assert.IsTrue(results.Contains(id5));
448488
}
449489

490+
[Test]
491+
public void TestDistinctLSub0()
492+
{
493+
var query = (from c in _collection.AsQueryable<C>()
494+
select c.L[0]).Distinct();
495+
var results = query.ToList();
496+
Assert.AreEqual(1, results.Count);
497+
Assert.IsTrue(results.Contains(2));
498+
}
499+
450500
[Test]
451501
public void TestDistinctS()
452502
{
@@ -457,6 +507,16 @@ public void TestDistinctS()
457507
Assert.IsTrue(results.Contains("x is 1"));
458508
}
459509

510+
[Test]
511+
public void TestDistinctSASub0()
512+
{
513+
var query = (from c in _collection.AsQueryable<C>()
514+
select c.SA[0]).Distinct();
515+
var results = query.ToList();
516+
Assert.AreEqual(1, results.Count);
517+
Assert.IsTrue(results.Contains("Tom"));
518+
}
519+
460520
[Test]
461521
public void TestDistinctX()
462522
{
@@ -471,6 +531,18 @@ public void TestDistinctX()
471531
Assert.IsTrue(results.Contains(5));
472532
}
473533

534+
[Test]
535+
public void TestDistinctXWithQuery()
536+
{
537+
var query = (from c in _collection.AsQueryable<C>()
538+
where c.X >3
539+
select c.X).Distinct();
540+
var results = query.ToList();
541+
Assert.AreEqual(2, results.Count);
542+
Assert.IsTrue(results.Contains(4));
543+
Assert.IsTrue(results.Contains(5));
544+
}
545+
474546
[Test]
475547
public void TestDistinctY()
476548
{
@@ -3226,6 +3298,190 @@ public void TestWhereLLengthNotEquals3Not()
32263298
Assert.AreEqual(1, Consume(query));
32273299
}
32283300

3301+
[Test]
3302+
public void TestWhereLSub1Equals3()
3303+
{
3304+
var query = from c in _collection.AsQueryable<C>()
3305+
where c.L[1] == 3
3306+
select c;
3307+
3308+
var translatedQuery = MongoQueryTranslator.Translate(query);
3309+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
3310+
Assert.AreSame(_collection, translatedQuery.Collection);
3311+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
3312+
3313+
var selectQuery = (SelectQuery)translatedQuery;
3314+
Assert.AreEqual("(C c) => (c.L.get_Item(1) == 3)", ExpressionFormatter.ToString(selectQuery.Where));
3315+
Assert.IsNull(selectQuery.OrderBy);
3316+
Assert.IsNull(selectQuery.Projection);
3317+
Assert.IsNull(selectQuery.Skip);
3318+
Assert.IsNull(selectQuery.Take);
3319+
3320+
Assert.AreEqual("{ \"l.1\" : 3 }", selectQuery.BuildQuery().ToJson());
3321+
Assert.AreEqual(1, Consume(query));
3322+
}
3323+
3324+
[Test]
3325+
public void TestWhereLSub1Equals3Not()
3326+
{
3327+
var query = from c in _collection.AsQueryable<C>()
3328+
where !(c.L[1] == 3)
3329+
select c;
3330+
3331+
var translatedQuery = MongoQueryTranslator.Translate(query);
3332+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
3333+
Assert.AreSame(_collection, translatedQuery.Collection);
3334+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
3335+
3336+
var selectQuery = (SelectQuery)translatedQuery;
3337+
Assert.AreEqual("(C c) => !(c.L.get_Item(1) == 3)", ExpressionFormatter.ToString(selectQuery.Where));
3338+
Assert.IsNull(selectQuery.OrderBy);
3339+
Assert.IsNull(selectQuery.Projection);
3340+
Assert.IsNull(selectQuery.Skip);
3341+
Assert.IsNull(selectQuery.Take);
3342+
3343+
Assert.AreEqual("{ \"l.1\" : { \"$ne\" : 3 } }", selectQuery.BuildQuery().ToJson());
3344+
Assert.AreEqual(4, Consume(query));
3345+
}
3346+
3347+
[Test]
3348+
public void TestWhereLSub1ModTwoEquals1()
3349+
{
3350+
var query = from c in _collection.AsQueryable<C>()
3351+
where c.L[1] % 2 == 1
3352+
select c;
3353+
3354+
var translatedQuery = MongoQueryTranslator.Translate(query);
3355+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
3356+
Assert.AreSame(_collection, translatedQuery.Collection);
3357+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
3358+
3359+
var selectQuery = (SelectQuery)translatedQuery;
3360+
Assert.AreEqual("(C c) => ((c.L.get_Item(1) % 2) == 1)", ExpressionFormatter.ToString(selectQuery.Where));
3361+
Assert.IsNull(selectQuery.OrderBy);
3362+
Assert.IsNull(selectQuery.Projection);
3363+
Assert.IsNull(selectQuery.Skip);
3364+
Assert.IsNull(selectQuery.Take);
3365+
3366+
Assert.AreEqual("{ \"l.1\" : { \"$mod\" : [2, 1] } }", selectQuery.BuildQuery().ToJson());
3367+
Assert.AreEqual(1, Consume(query));
3368+
}
3369+
3370+
[Test]
3371+
public void TestWhereLSub1ModTwoEquals1Not()
3372+
{
3373+
var query = from c in _collection.AsQueryable<C>()
3374+
where !(c.L[1] % 2 == 1)
3375+
select c;
3376+
3377+
var translatedQuery = MongoQueryTranslator.Translate(query);
3378+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
3379+
Assert.AreSame(_collection, translatedQuery.Collection);
3380+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
3381+
3382+
var selectQuery = (SelectQuery)translatedQuery;
3383+
Assert.AreEqual("(C c) => !((c.L.get_Item(1) % 2) == 1)", ExpressionFormatter.ToString(selectQuery.Where));
3384+
Assert.IsNull(selectQuery.OrderBy);
3385+
Assert.IsNull(selectQuery.Projection);
3386+
Assert.IsNull(selectQuery.Skip);
3387+
Assert.IsNull(selectQuery.Take);
3388+
3389+
Assert.AreEqual("{ \"l.1\" : { \"$not\" : { \"$mod\" : [2, 1] } } }", selectQuery.BuildQuery().ToJson());
3390+
Assert.AreEqual(4, Consume(query));
3391+
}
3392+
3393+
[Test]
3394+
public void TestWhereLSub1ModTwoNotEquals1()
3395+
{
3396+
var query = from c in _collection.AsQueryable<C>()
3397+
where c.L[1] % 2 != 1
3398+
select c;
3399+
3400+
var translatedQuery = MongoQueryTranslator.Translate(query);
3401+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
3402+
Assert.AreSame(_collection, translatedQuery.Collection);
3403+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
3404+
3405+
var selectQuery = (SelectQuery)translatedQuery;
3406+
Assert.AreEqual("(C c) => ((c.L.get_Item(1) % 2) != 1)", ExpressionFormatter.ToString(selectQuery.Where));
3407+
Assert.IsNull(selectQuery.OrderBy);
3408+
Assert.IsNull(selectQuery.Projection);
3409+
Assert.IsNull(selectQuery.Skip);
3410+
Assert.IsNull(selectQuery.Take);
3411+
3412+
Assert.AreEqual("{ \"l.1\" : { \"$not\" : { \"$mod\" : [2, 1] } } }", selectQuery.BuildQuery().ToJson());
3413+
Assert.AreEqual(4, Consume(query));
3414+
}
3415+
3416+
[Test]
3417+
public void TestWhereLSub1ModTwoNotEquals1Not()
3418+
{
3419+
var query = from c in _collection.AsQueryable<C>()
3420+
where !(c.L[1] % 2 != 1)
3421+
select c;
3422+
3423+
var translatedQuery = MongoQueryTranslator.Translate(query);
3424+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
3425+
Assert.AreSame(_collection, translatedQuery.Collection);
3426+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
3427+
3428+
var selectQuery = (SelectQuery)translatedQuery;
3429+
Assert.AreEqual("(C c) => !((c.L.get_Item(1) % 2) != 1)", ExpressionFormatter.ToString(selectQuery.Where));
3430+
Assert.IsNull(selectQuery.OrderBy);
3431+
Assert.IsNull(selectQuery.Projection);
3432+
Assert.IsNull(selectQuery.Skip);
3433+
Assert.IsNull(selectQuery.Take);
3434+
3435+
Assert.AreEqual("{ \"l.1\" : { \"$mod\" : [2, 1] } }", selectQuery.BuildQuery().ToJson());
3436+
Assert.AreEqual(1, Consume(query));
3437+
}
3438+
3439+
[Test]
3440+
public void TestWhereLSub1NotEquals3()
3441+
{
3442+
var query = from c in _collection.AsQueryable<C>()
3443+
where c.L[1] != 3
3444+
select c;
3445+
3446+
var translatedQuery = MongoQueryTranslator.Translate(query);
3447+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
3448+
Assert.AreSame(_collection, translatedQuery.Collection);
3449+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
3450+
3451+
var selectQuery = (SelectQuery)translatedQuery;
3452+
Assert.AreEqual("(C c) => (c.L.get_Item(1) != 3)", ExpressionFormatter.ToString(selectQuery.Where));
3453+
Assert.IsNull(selectQuery.OrderBy);
3454+
Assert.IsNull(selectQuery.Projection);
3455+
Assert.IsNull(selectQuery.Skip);
3456+
Assert.IsNull(selectQuery.Take);
3457+
3458+
Assert.AreEqual("{ \"l.1\" : { \"$ne\" : 3 } }", selectQuery.BuildQuery().ToJson());
3459+
Assert.AreEqual(4, Consume(query));
3460+
}
3461+
3462+
[Test]
3463+
public void TestWhereLSub1NotEquals3Not()
3464+
{
3465+
var query = from c in _collection.AsQueryable<C>()
3466+
where !(c.L[1] != 3)
3467+
select c;
3468+
3469+
var translatedQuery = MongoQueryTranslator.Translate(query);
3470+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
3471+
Assert.AreSame(_collection, translatedQuery.Collection);
3472+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
3473+
3474+
var selectQuery = (SelectQuery)translatedQuery;
3475+
Assert.AreEqual("(C c) => !(c.L.get_Item(1) != 3)", ExpressionFormatter.ToString(selectQuery.Where));
3476+
Assert.IsNull(selectQuery.OrderBy);
3477+
Assert.IsNull(selectQuery.Projection);
3478+
Assert.IsNull(selectQuery.Skip);
3479+
Assert.IsNull(selectQuery.Take);
3480+
3481+
Assert.AreEqual("{ \"l.1\" : 3 }", selectQuery.BuildQuery().ToJson());
3482+
Assert.AreEqual(1, Consume(query));
3483+
}
3484+
32293485
[Test]
32303486
public void TestWhereSASub0ContainsO()
32313487
{

0 commit comments

Comments
 (0)