Skip to content

Commit f3bd74b

Browse files
craiggwilsonrstam
authored andcommitted
https://github.com/ray2k submitted pull request for adding ToLower/ToUpper.
1 parent a1da18e commit f3bd74b

File tree

2 files changed

+343
-0
lines changed

2 files changed

+343
-0
lines changed

Driver/Linq/Translators/PredicateTranslator.cs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,12 @@ private IMongoQuery BuildComparisonQuery(BinaryExpression binaryExpression)
258258
return query;
259259
}
260260

261+
query = BuildStringCaseComparisonQuery(variableExpression, operatorType, constantExpression);
262+
if (query != null)
263+
{
264+
return query;
265+
}
266+
261267
query = BuildTypeComparisonQuery(variableExpression, operatorType, constantExpression);
262268
if (query != null)
263269
{
@@ -1041,6 +1047,59 @@ private IMongoQuery BuildStringLengthQuery(Expression variableExpression, Expres
10411047
return null;
10421048
}
10431049

1050+
private IMongoQuery BuildStringCaseComparisonQuery(Expression variableExpression, ExpressionType operatorType, ConstantExpression constantExpression)
1051+
{
1052+
var methodExpression = variableExpression as MethodCallExpression;
1053+
if (methodExpression != null)
1054+
{
1055+
var sourceExpression = methodExpression.Object as MemberExpression;
1056+
1057+
if (methodExpression.Type == typeof(string) && sourceExpression != null)
1058+
{
1059+
var serializationInfo = _serializationInfoHelper.GetSerializationInfo(methodExpression.Object);
1060+
var serializedValue = _serializationInfoHelper.SerializeValue(serializationInfo, constantExpression.Value);
1061+
var coalescedStringValue = constantExpression.Value == null ? string.Empty : serializedValue.AsString;
1062+
1063+
string regexPattern = "/^" + Regex.Escape(coalescedStringValue) + "$/i";
1064+
var regex = new BsonRegularExpression(regexPattern);
1065+
1066+
bool caseMismatch = false;
1067+
1068+
if (methodExpression.Method.Name == "ToLower" && (coalescedStringValue != coalescedStringValue.ToLower()))
1069+
caseMismatch = true;
1070+
else if (methodExpression.Method.Name == "ToUpper" && (coalescedStringValue != coalescedStringValue.ToUpper()))
1071+
caseMismatch = true;
1072+
else if (constantExpression.Value == null)
1073+
caseMismatch = true;
1074+
1075+
if (operatorType == ExpressionType.Equal)
1076+
{
1077+
// if comparing Foo.ToLower() == "Some Non Lower Case String"
1078+
// then that is always false for all documents
1079+
if (caseMismatch)
1080+
return Query.Exists("_id", false);
1081+
1082+
return Query.And(Query.Exists(serializationInfo.ElementName, true),
1083+
Query.Matches(serializationInfo.ElementName, regex));
1084+
}
1085+
else if (operatorType == ExpressionType.NotEqual)
1086+
{
1087+
// if comparing Foo.ToLower() != "Some Non Lower Case String"
1088+
// then that is always true as long as Foo is set/exists
1089+
if (caseMismatch)
1090+
return Query.Exists(serializationInfo.ElementName, true);
1091+
1092+
return Query.And(Query.Exists(serializationInfo.ElementName, true),
1093+
Query.Not(serializationInfo.ElementName).Matches(regex));
1094+
}
1095+
else
1096+
return null;
1097+
}
1098+
}
1099+
1100+
return null;
1101+
}
1102+
10441103
private IMongoQuery BuildStringQuery(MethodCallExpression methodCallExpression)
10451104
{
10461105
if (methodCallExpression.Method.DeclaringType != typeof(string))

DriverUnitTests/Linq/SelectQueryTests.cs

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5565,6 +5565,290 @@ where c.S.TrimStart(' ', '.', '-', '\t').TrimEnd().ToLower().Contains("xyz")
55655565
Assert.AreEqual(1, Consume(query));
55665566
}
55675567

5568+
[Test]
5569+
public void TestWhereSToLowerEqualsConstantLowerCaseValue()
5570+
{
5571+
var query = from c in _collection.AsQueryable<C>()
5572+
where c.S.ToLower() == "abc"
5573+
select c;
5574+
5575+
var translatedQuery = MongoQueryTranslator.Translate(query);
5576+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
5577+
Assert.AreSame(_collection, translatedQuery.Collection);
5578+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
5579+
5580+
var selectQuery = (SelectQuery)translatedQuery;
5581+
Assert.AreEqual("(C c) => (c.S.ToLower() == \"abc\")", ExpressionFormatter.ToString(selectQuery.Where));
5582+
5583+
Assert.IsNull(selectQuery.OrderBy);
5584+
Assert.IsNull(selectQuery.Projection);
5585+
Assert.IsNull(selectQuery.Skip);
5586+
Assert.IsNull(selectQuery.Take);
5587+
5588+
Assert.AreEqual("{ \"$and\" : [{ \"s\" : { \"$exists\" : true } }, { \"s\" : /^abc$/i }] }", selectQuery.BuildQuery().ToJson());
5589+
Assert.AreEqual(1, Consume(query));
5590+
}
5591+
5592+
[Test]
5593+
public void TestWhereSToLowerDoesNotEqualConstantLowerCaseValue()
5594+
{
5595+
var query = from c in _collection.AsQueryable<C>()
5596+
where c.S.ToLower() != "abc"
5597+
select c;
5598+
5599+
var translatedQuery = MongoQueryTranslator.Translate(query);
5600+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
5601+
Assert.AreSame(_collection, translatedQuery.Collection);
5602+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
5603+
5604+
var selectQuery = (SelectQuery)translatedQuery;
5605+
Assert.AreEqual("(C c) => (c.S.ToLower() != \"abc\")", ExpressionFormatter.ToString(selectQuery.Where));
5606+
5607+
Assert.IsNull(selectQuery.OrderBy);
5608+
Assert.IsNull(selectQuery.Projection);
5609+
Assert.IsNull(selectQuery.Skip);
5610+
Assert.IsNull(selectQuery.Take);
5611+
5612+
Assert.AreEqual("{ \"s\" : { \"$exists\" : true, \"$not\" : /^abc$/i } }", selectQuery.BuildQuery().ToJson());
5613+
Assert.AreEqual(1, Consume(query));
5614+
}
5615+
5616+
[Test]
5617+
public void TestWhereSToLowerEqualsConstantMixedCaseValue()
5618+
{
5619+
var query = from c in _collection.AsQueryable<C>()
5620+
where c.S.ToLower() == "Abc"
5621+
select c;
5622+
5623+
var translatedQuery = MongoQueryTranslator.Translate(query);
5624+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
5625+
Assert.AreSame(_collection, translatedQuery.Collection);
5626+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
5627+
5628+
var selectQuery = (SelectQuery)translatedQuery;
5629+
Assert.AreEqual("(C c) => (c.S.ToLower() == \"Abc\")", ExpressionFormatter.ToString(selectQuery.Where));
5630+
5631+
Assert.IsNull(selectQuery.OrderBy);
5632+
Assert.IsNull(selectQuery.Projection);
5633+
Assert.IsNull(selectQuery.Skip);
5634+
Assert.IsNull(selectQuery.Take);
5635+
5636+
Assert.AreEqual("{ \"_id\" : { \"$exists\" : false } }", selectQuery.BuildQuery().ToJson());
5637+
Assert.AreEqual(0, Consume(query));
5638+
}
5639+
5640+
[Test]
5641+
public void TestWhereSToLowerDoesNotEqualConstantMixedCaseValue()
5642+
{
5643+
var query = from c in _collection.AsQueryable<C>()
5644+
where c.S.ToLower() != "Abc"
5645+
select c;
5646+
5647+
var translatedQuery = MongoQueryTranslator.Translate(query);
5648+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
5649+
Assert.AreSame(_collection, translatedQuery.Collection);
5650+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
5651+
5652+
var selectQuery = (SelectQuery)translatedQuery;
5653+
Assert.AreEqual("(C c) => (c.S.ToLower() != \"Abc\")", ExpressionFormatter.ToString(selectQuery.Where));
5654+
5655+
Assert.IsNull(selectQuery.OrderBy);
5656+
Assert.IsNull(selectQuery.Projection);
5657+
Assert.IsNull(selectQuery.Skip);
5658+
Assert.IsNull(selectQuery.Take);
5659+
5660+
Assert.AreEqual("{ \"s\" : { \"$exists\" : true } }", selectQuery.BuildQuery().ToJson());
5661+
Assert.AreEqual(2, Consume(query));
5662+
}
5663+
5664+
[Test]
5665+
public void TestWhereSToLowerEqualsNullValue()
5666+
{
5667+
var query = from c in _collection.AsQueryable<C>()
5668+
where c.S.ToLower() == (string)null
5669+
select c;
5670+
5671+
var translatedQuery = MongoQueryTranslator.Translate(query);
5672+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
5673+
Assert.AreSame(_collection, translatedQuery.Collection);
5674+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
5675+
5676+
var selectQuery = (SelectQuery)translatedQuery;
5677+
5678+
Assert.IsNull(selectQuery.OrderBy);
5679+
Assert.IsNull(selectQuery.Projection);
5680+
Assert.IsNull(selectQuery.Skip);
5681+
Assert.IsNull(selectQuery.Take);
5682+
5683+
Assert.AreEqual("{ \"_id\" : { \"$exists\" : false } }", selectQuery.BuildQuery().ToJson());
5684+
Assert.AreEqual(0, Consume(query));
5685+
}
5686+
5687+
[Test]
5688+
public void TestWhereSToLowerDoesNotEqualNullValue()
5689+
{
5690+
var query = from c in _collection.AsQueryable<C>()
5691+
where c.S.ToLower() != (string)null
5692+
select c;
5693+
5694+
var translatedQuery = MongoQueryTranslator.Translate(query);
5695+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
5696+
Assert.AreSame(_collection, translatedQuery.Collection);
5697+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
5698+
5699+
var selectQuery = (SelectQuery)translatedQuery;
5700+
5701+
Assert.IsNull(selectQuery.OrderBy);
5702+
Assert.IsNull(selectQuery.Projection);
5703+
Assert.IsNull(selectQuery.Skip);
5704+
Assert.IsNull(selectQuery.Take);
5705+
5706+
Assert.AreEqual("{ \"s\" : { \"$exists\" : true } }", selectQuery.BuildQuery().ToJson());
5707+
Assert.AreEqual(2, Consume(query));
5708+
}
5709+
5710+
[Test]
5711+
public void TestWhereSToUpperEqualsConstantLowerCaseValue()
5712+
{
5713+
var query = from c in _collection.AsQueryable<C>()
5714+
where c.S.ToUpper() == "abc"
5715+
select c;
5716+
5717+
var translatedQuery = MongoQueryTranslator.Translate(query);
5718+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
5719+
Assert.AreSame(_collection, translatedQuery.Collection);
5720+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
5721+
5722+
var selectQuery = (SelectQuery)translatedQuery;
5723+
Assert.AreEqual("(C c) => (c.S.ToUpper() == \"abc\")", ExpressionFormatter.ToString(selectQuery.Where));
5724+
5725+
Assert.IsNull(selectQuery.OrderBy);
5726+
Assert.IsNull(selectQuery.Projection);
5727+
Assert.IsNull(selectQuery.Skip);
5728+
Assert.IsNull(selectQuery.Take);
5729+
5730+
Assert.AreEqual("{ \"_id\" : { \"$exists\" : false } }", selectQuery.BuildQuery().ToJson());
5731+
Assert.AreEqual(0, Consume(query));
5732+
}
5733+
5734+
[Test]
5735+
public void TestWhereSToUpperDoesNotEqualConstantLowerCaseValue()
5736+
{
5737+
var query = from c in _collection.AsQueryable<C>()
5738+
where c.S.ToUpper() != "abc"
5739+
select c;
5740+
5741+
var translatedQuery = MongoQueryTranslator.Translate(query);
5742+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
5743+
Assert.AreSame(_collection, translatedQuery.Collection);
5744+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
5745+
5746+
var selectQuery = (SelectQuery)translatedQuery;
5747+
Assert.AreEqual("(C c) => (c.S.ToUpper() != \"abc\")", ExpressionFormatter.ToString(selectQuery.Where));
5748+
5749+
Assert.IsNull(selectQuery.OrderBy);
5750+
Assert.IsNull(selectQuery.Projection);
5751+
Assert.IsNull(selectQuery.Skip);
5752+
Assert.IsNull(selectQuery.Take);
5753+
5754+
Assert.AreEqual("{ \"s\" : { \"$exists\" : true } }", selectQuery.BuildQuery().ToJson());
5755+
Assert.AreEqual(2, Consume(query));
5756+
}
5757+
5758+
[Test]
5759+
public void TestWhereSToUpperEqualsConstantMixedCaseValue()
5760+
{
5761+
var query = from c in _collection.AsQueryable<C>()
5762+
where c.S.ToUpper() == "Abc"
5763+
select c;
5764+
5765+
var translatedQuery = MongoQueryTranslator.Translate(query);
5766+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
5767+
Assert.AreSame(_collection, translatedQuery.Collection);
5768+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
5769+
5770+
var selectQuery = (SelectQuery)translatedQuery;
5771+
Assert.AreEqual("(C c) => (c.S.ToUpper() == \"Abc\")", ExpressionFormatter.ToString(selectQuery.Where));
5772+
5773+
Assert.IsNull(selectQuery.OrderBy);
5774+
Assert.IsNull(selectQuery.Projection);
5775+
Assert.IsNull(selectQuery.Skip);
5776+
Assert.IsNull(selectQuery.Take);
5777+
5778+
Assert.AreEqual("{ \"_id\" : { \"$exists\" : false } }", selectQuery.BuildQuery().ToJson());
5779+
Assert.AreEqual(0, Consume(query));
5780+
}
5781+
5782+
[Test]
5783+
public void TestWhereSToUpperDoesNotEqualConstantMixedCaseValue()
5784+
{
5785+
var query = from c in _collection.AsQueryable<C>()
5786+
where c.S.ToUpper() != "Abc"
5787+
select c;
5788+
5789+
var translatedQuery = MongoQueryTranslator.Translate(query);
5790+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
5791+
Assert.AreSame(_collection, translatedQuery.Collection);
5792+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
5793+
5794+
var selectQuery = (SelectQuery)translatedQuery;
5795+
Assert.AreEqual("(C c) => (c.S.ToUpper() != \"Abc\")", ExpressionFormatter.ToString(selectQuery.Where));
5796+
5797+
Assert.IsNull(selectQuery.OrderBy);
5798+
Assert.IsNull(selectQuery.Projection);
5799+
Assert.IsNull(selectQuery.Skip);
5800+
Assert.IsNull(selectQuery.Take);
5801+
5802+
Assert.AreEqual("{ \"s\" : { \"$exists\" : true } }", selectQuery.BuildQuery().ToJson());
5803+
Assert.AreEqual(2, Consume(query));
5804+
}
5805+
5806+
[Test]
5807+
public void TestWhereSToUpperEqualsNullValue()
5808+
{
5809+
var query = from c in _collection.AsQueryable<C>()
5810+
where c.S.ToUpper() == (string)null
5811+
select c;
5812+
5813+
var translatedQuery = MongoQueryTranslator.Translate(query);
5814+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
5815+
Assert.AreSame(_collection, translatedQuery.Collection);
5816+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
5817+
5818+
var selectQuery = (SelectQuery)translatedQuery;
5819+
5820+
Assert.IsNull(selectQuery.OrderBy);
5821+
Assert.IsNull(selectQuery.Projection);
5822+
Assert.IsNull(selectQuery.Skip);
5823+
Assert.IsNull(selectQuery.Take);
5824+
5825+
Assert.AreEqual("{ \"_id\" : { \"$exists\" : false } }", selectQuery.BuildQuery().ToJson());
5826+
Assert.AreEqual(0, Consume(query));
5827+
}
5828+
5829+
[Test]
5830+
public void TestWhereSToUpperDoesNotEqualNullValue()
5831+
{
5832+
var query = from c in _collection.AsQueryable<C>()
5833+
where c.S.ToUpper() != (string)null
5834+
select c;
5835+
5836+
var translatedQuery = MongoQueryTranslator.Translate(query);
5837+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
5838+
Assert.AreSame(_collection, translatedQuery.Collection);
5839+
Assert.AreSame(typeof(C), translatedQuery.DocumentType);
5840+
5841+
var selectQuery = (SelectQuery)translatedQuery;
5842+
5843+
Assert.IsNull(selectQuery.OrderBy);
5844+
Assert.IsNull(selectQuery.Projection);
5845+
Assert.IsNull(selectQuery.Skip);
5846+
Assert.IsNull(selectQuery.Take);
5847+
5848+
Assert.AreEqual("{ \"s\" : { \"$exists\" : true } }", selectQuery.BuildQuery().ToJson());
5849+
Assert.AreEqual(2, Consume(query));
5850+
}
5851+
55685852
[Test]
55695853
public void TestWhereSystemProfileInfoDurationGreatherThan10Seconds()
55705854
{

0 commit comments

Comments
 (0)