Skip to content

Commit 58bdc72

Browse files
author
rstam
committed
Added support for static and instance Equals method in LINQ queries.
1 parent 2576b87 commit 58bdc72

File tree

2 files changed

+238
-0
lines changed

2 files changed

+238
-0
lines changed

Driver/Linq/Translators/SelectQuery.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,11 @@ private IMongoQuery BuildComparisonQuery(BinaryExpression binaryExpression)
365365
return query;
366366
}
367367

368+
return BuildComparisonQuery(variableExpression, operatorType, constantExpression);
369+
}
370+
371+
private IMongoQuery BuildComparisonQuery(Expression variableExpression, ExpressionType operatorType, ConstantExpression constantExpression)
372+
{
368373
BsonSerializationInfo serializationInfo = null;
369374
var value = constantExpression.Value;
370375

@@ -490,6 +495,54 @@ private IMongoQuery BuildContainsQuery(MethodCallExpression methodCallExpression
490495
return null;
491496
}
492497

498+
private IMongoQuery BuildEqualsQuery(MethodCallExpression methodCallExpression)
499+
{
500+
var arguments = methodCallExpression.Arguments.ToArray();
501+
502+
// assume that static and instance Equals mean the same thing for all classes (i.e. an equality test)
503+
Expression firstExpression = null;
504+
Expression secondExpression = null;
505+
if (methodCallExpression.Object == null)
506+
{
507+
// static Equals method
508+
if (arguments.Length == 2)
509+
{
510+
firstExpression = arguments[0];
511+
secondExpression = arguments[1];
512+
}
513+
}
514+
else
515+
{
516+
// instance Equals method
517+
if (arguments.Length == 1)
518+
{
519+
firstExpression = methodCallExpression.Object;
520+
secondExpression = arguments[0];
521+
}
522+
}
523+
524+
if (firstExpression != null && secondExpression != null)
525+
{
526+
// the constant could be either expression
527+
var variableExpression = firstExpression;
528+
var constantExpression = secondExpression as ConstantExpression;
529+
if (constantExpression == null)
530+
{
531+
constantExpression = firstExpression as ConstantExpression;
532+
variableExpression = secondExpression;
533+
}
534+
535+
if (constantExpression == null)
536+
{
537+
return null;
538+
}
539+
540+
return BuildComparisonQuery(variableExpression, ExpressionType.Equal, constantExpression);
541+
}
542+
543+
return null;
544+
}
545+
493546
private IMongoQuery BuildInQuery(MethodCallExpression methodCallExpression)
494547
{
495548
if (methodCallExpression.Method.DeclaringType == typeof(LinqToMongo))
@@ -585,6 +638,7 @@ private IMongoQuery BuildMethodCallQuery(MethodCallExpression methodCallExpressi
585638
case "ContainsAll": return BuildContainsAllQuery(methodCallExpression);
586639
case "ContainsAny": return BuildContainsAnyQuery(methodCallExpression);
587640
case "EndsWith": return BuildStringQuery(methodCallExpression);
641+
case "Equals": return BuildEqualsQuery(methodCallExpression);
588642
case "In": return BuildInQuery(methodCallExpression);
589643
case "Inject": return BuildInjectQuery(methodCallExpression);
590644
case "IsMatch": return BuildIsMatchQuery(methodCallExpression);

DriverUnitTests/Linq/SelectQueryTests.cs

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4305,6 +4305,144 @@ where c.S.Count() == 3
43054305
Assert.AreEqual(1, Consume(query));
43064306
}
43074307

4308+
[Test]
4309+
public void TestWhereSEqualsAbc()
4310+
{
4311+
var query = from c in _collection.AsQueryable<C>()
4312+
where c.S == "abc"
4313+
select c;
4314+
4315+
var translatedQuery = MongoQueryTranslator.Translate(query);
4316+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
4317+
Assert.AreSame(_collection, translatedQuery.Collection);
4318+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
4319+
4320+
var selectQuery = (SelectQuery)translatedQuery;
4321+
Assert.AreEqual("(C c) => (c.S == \"abc\")", ExpressionFormatter.ToString(selectQuery.Where));
4322+
Assert.IsNull(selectQuery.OrderBy);
4323+
Assert.IsNull(selectQuery.Projection);
4324+
Assert.IsNull(selectQuery.Skip);
4325+
Assert.IsNull(selectQuery.Take);
4326+
4327+
Assert.AreEqual("{ \"s\" : \"abc\" }", selectQuery.BuildQuery().ToJson());
4328+
Assert.AreEqual(1, Consume(query));
4329+
}
4330+
4331+
[Test]
4332+
public void TestWhereSEqualsAbcNot()
4333+
{
4334+
var query = from c in _collection.AsQueryable<C>()
4335+
where !(c.S == "abc")
4336+
select c;
4337+
4338+
var translatedQuery = MongoQueryTranslator.Translate(query);
4339+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
4340+
Assert.AreSame(_collection, translatedQuery.Collection);
4341+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
4342+
4343+
var selectQuery = (SelectQuery)translatedQuery;
4344+
Assert.AreEqual("(C c) => !(c.S == \"abc\")", ExpressionFormatter.ToString(selectQuery.Where));
4345+
Assert.IsNull(selectQuery.OrderBy);
4346+
Assert.IsNull(selectQuery.Projection);
4347+
Assert.IsNull(selectQuery.Skip);
4348+
Assert.IsNull(selectQuery.Take);
4349+
4350+
Assert.AreEqual("{ \"s\" : { \"$ne\" : \"abc\" } }", selectQuery.BuildQuery().ToJson());
4351+
Assert.AreEqual(4, Consume(query));
4352+
}
4353+
4354+
[Test]
4355+
public void TestWhereSEqualsMethodAbc()
4356+
{
4357+
var query = from c in _collection.AsQueryable<C>()
4358+
where c.S.Equals("abc")
4359+
select c;
4360+
4361+
var translatedQuery = MongoQueryTranslator.Translate(query);
4362+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
4363+
Assert.AreSame(_collection, translatedQuery.Collection);
4364+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
4365+
4366+
var selectQuery = (SelectQuery)translatedQuery;
4367+
Assert.AreEqual("(C c) => c.S.Equals(\"abc\")", ExpressionFormatter.ToString(selectQuery.Where));
4368+
Assert.IsNull(selectQuery.OrderBy);
4369+
Assert.IsNull(selectQuery.Projection);
4370+
Assert.IsNull(selectQuery.Skip);
4371+
Assert.IsNull(selectQuery.Take);
4372+
4373+
Assert.AreEqual("{ \"s\" : \"abc\" }", selectQuery.BuildQuery().ToJson());
4374+
Assert.AreEqual(1, Consume(query));
4375+
}
4376+
4377+
[Test]
4378+
public void TestWhereSEqualsMethodAbcNot()
4379+
{
4380+
var query = from c in _collection.AsQueryable<C>()
4381+
where !(c.S.Equals("abc"))
4382+
select c;
4383+
4384+
var translatedQuery = MongoQueryTranslator.Translate(query);
4385+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
4386+
Assert.AreSame(_collection, translatedQuery.Collection);
4387+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
4388+
4389+
var selectQuery = (SelectQuery)translatedQuery;
4390+
Assert.AreEqual("(C c) => !c.S.Equals(\"abc\")", ExpressionFormatter.ToString(selectQuery.Where));
4391+
Assert.IsNull(selectQuery.OrderBy);
4392+
Assert.IsNull(selectQuery.Projection);
4393+
Assert.IsNull(selectQuery.Skip);
4394+
Assert.IsNull(selectQuery.Take);
4395+
4396+
Assert.AreEqual("{ \"s\" : { \"$ne\" : \"abc\" } }", selectQuery.BuildQuery().ToJson());
4397+
Assert.AreEqual(4, Consume(query));
4398+
}
4399+
4400+
[Test]
4401+
public void TestWhereSEqualsStaticMethodAbc()
4402+
{
4403+
var query = from c in _collection.AsQueryable<C>()
4404+
where string.Equals(c.S, "abc")
4405+
select c;
4406+
4407+
var translatedQuery = MongoQueryTranslator.Translate(query);
4408+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
4409+
Assert.AreSame(_collection, translatedQuery.Collection);
4410+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
4411+
4412+
var selectQuery = (SelectQuery)translatedQuery;
4413+
Assert.AreEqual("(C c) => String.Equals(c.S, \"abc\")", ExpressionFormatter.ToString(selectQuery.Where));
4414+
Assert.IsNull(selectQuery.OrderBy);
4415+
Assert.IsNull(selectQuery.Projection);
4416+
Assert.IsNull(selectQuery.Skip);
4417+
Assert.IsNull(selectQuery.Take);
4418+
4419+
Assert.AreEqual("{ \"s\" : \"abc\" }", selectQuery.BuildQuery().ToJson());
4420+
Assert.AreEqual(1, Consume(query));
4421+
}
4422+
4423+
[Test]
4424+
public void TestWhereSEqualsStaticMethodAbcNot()
4425+
{
4426+
var query = from c in _collection.AsQueryable<C>()
4427+
where !string.Equals(c.S, "abc")
4428+
select c;
4429+
4430+
var translatedQuery = MongoQueryTranslator.Translate(query);
4431+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
4432+
Assert.AreSame(_collection, translatedQuery.Collection);
4433+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
4434+
4435+
var selectQuery = (SelectQuery)translatedQuery;
4436+
Assert.AreEqual("(C c) => !String.Equals(c.S, \"abc\")", ExpressionFormatter.ToString(selectQuery.Where));
4437+
Assert.IsNull(selectQuery.OrderBy);
4438+
Assert.IsNull(selectQuery.Projection);
4439+
Assert.IsNull(selectQuery.Skip);
4440+
Assert.IsNull(selectQuery.Take);
4441+
4442+
Assert.AreEqual("{ \"s\" : { \"$ne\" : \"abc\" } }", selectQuery.BuildQuery().ToJson());
4443+
Assert.AreEqual(4, Consume(query));
4444+
}
4445+
43084446
[Test]
43094447
public void TestWhereSEndsWithAbc()
43104448
{
@@ -4972,6 +5110,52 @@ public void TestWhereSLengthNotEquals3Not()
49725110
Assert.AreEqual(1, Consume(query));
49735111
}
49745112

5113+
[Test]
5114+
public void TestWhereSNotEqualsAbc()
5115+
{
5116+
var query = from c in _collection.AsQueryable<C>()
5117+
where c.S != "abc"
5118+
select c;
5119+
5120+
var translatedQuery = MongoQueryTranslator.Translate(query);
5121+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
5122+
Assert.AreSame(_collection, translatedQuery.Collection);
5123+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
5124+
5125+
var selectQuery = (SelectQuery)translatedQuery;
5126+
Assert.AreEqual("(C c) => (c.S != \"abc\")", ExpressionFormatter.ToString(selectQuery.Where));
5127+
Assert.IsNull(selectQuery.OrderBy);
5128+
Assert.IsNull(selectQuery.Projection);
5129+
Assert.IsNull(selectQuery.Skip);
5130+
Assert.IsNull(selectQuery.Take);
5131+
5132+
Assert.AreEqual("{ \"s\" : { \"$ne\" : \"abc\" } }", selectQuery.BuildQuery().ToJson());
5133+
Assert.AreEqual(4, Consume(query));
5134+
}
5135+
5136+
[Test]
5137+
public void TestWhereSNotEqualsAbcNot()
5138+
{
5139+
var query = from c in _collection.AsQueryable<C>()
5140+
where !(c.S != "abc")
5141+
select c;
5142+
5143+
var translatedQuery = MongoQueryTranslator.Translate(query);
5144+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
5145+
Assert.AreSame(_collection, translatedQuery.Collection);
5146+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
5147+
5148+
var selectQuery = (SelectQuery)translatedQuery;
5149+
Assert.AreEqual("(C c) => !(c.S != \"abc\")", ExpressionFormatter.ToString(selectQuery.Where));
5150+
Assert.IsNull(selectQuery.OrderBy);
5151+
Assert.IsNull(selectQuery.Projection);
5152+
Assert.IsNull(selectQuery.Skip);
5153+
Assert.IsNull(selectQuery.Take);
5154+
5155+
Assert.AreEqual("{ \"s\" : \"abc\" }", selectQuery.BuildQuery().ToJson());
5156+
Assert.AreEqual(1, Consume(query));
5157+
}
5158+
49755159
[Test]
49765160
public void TestWhereSStartsWithAbc()
49775161
{

0 commit comments

Comments
 (0)