Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added support for string IndexOfAny in LINQ query where clauses.

  • Loading branch information...
commit 2576b87e01a9731565ab22034838c04d35f893eb 1 parent 3c814ca
rstam authored
View
51 Driver/Linq/Translators/SelectQuery.cs
@@ -763,7 +763,9 @@ private IMongoQuery BuildStringIndexOfQuery(Expression variableExpression, Expre
var index = ToInt32(constantExpression);
var methodCallExpression = variableExpression as MethodCallExpression;
- if (methodCallExpression != null && methodCallExpression.Method.Name == "IndexOf" && methodCallExpression.Method.DeclaringType == typeof(string))
+ if (methodCallExpression != null &&
+ (methodCallExpression.Method.Name == "IndexOf" || methodCallExpression.Method.Name == "IndexOfAny") &&
+ methodCallExpression.Method.DeclaringType == typeof(string))
{
var serializationInfo = GetSerializationInfo(methodCallExpression.Object);
if (serializationInfo == null)
@@ -807,14 +809,29 @@ private IMongoQuery BuildStringIndexOfQuery(Expression variableExpression, Expre
}
string pattern = null;
- if (value.GetType() == typeof(char))
+ if (value.GetType() == typeof(char) || value.GetType() == typeof(char[]))
{
- var escapedChar = Regex.Escape(((char)value).ToString());
+ char[] chars;
+ if (value.GetType() == typeof(char))
+ {
+ chars = new char[] { (char)value };
+ }
+ else
+ {
+ chars = (char[])value;
+ }
+ var positiveClass = string.Join("", chars.Select(c => (c == '-') ? "\\-" : (c == ']') ? "\\]" : Regex.Escape(c.ToString())).ToArray());
+ var negativeClass = "[^" + positiveClass + "]";
+ if (chars.Length > 1)
+ {
+ positiveClass = "[" + positiveClass + "]";
+ }
+
if (startIndex == -1)
{
// the regex for: IndexOf(c) == index
// is: /^[^c]{index}c/
- pattern = string.Format("^[^{0}]{{{1}}}{0}", escapedChar, index);
+ pattern = string.Format("^{0}{{{1}}}{2}", negativeClass, index, positiveClass);
}
else
{
@@ -822,7 +839,7 @@ private IMongoQuery BuildStringIndexOfQuery(Expression variableExpression, Expre
{
// the regex for: IndexOf(c, startIndex) == index
// is: /^.{startIndex}[^c]{index - startIndex}c/
- pattern = string.Format("^.{{{1}}}[^{0}]{{{2}}}{0}", escapedChar, startIndex, index - startIndex);
+ pattern = string.Format("^.{{{0}}}{1}{{{2}}}{3}", startIndex, negativeClass, index - startIndex, positiveClass);
}
else
{
@@ -835,7 +852,7 @@ private IMongoQuery BuildStringIndexOfQuery(Expression variableExpression, Expre
{
// the regex for: IndexOf(c, startIndex, count) == index
// is: /^.{startIndex}(?=.{count})[^c]{index - startIndex}c/
- pattern = string.Format("^.{{{1}}}(?=.{{{2}}})[^{0}]{{{3}}}{0}", escapedChar, startIndex, count, index - startIndex);
+ pattern = string.Format("^.{{{0}}}(?=.{{{1}}}){2}{{{3}}}{4}", startIndex, count, negativeClass, index - startIndex, positiveClass);
}
}
}
@@ -1233,26 +1250,12 @@ private string GetTrimCharsPattern(Expression trimCharsExpression)
}
// build a pattern that matches the characters to be trimmed
- var sb = new StringBuilder();
- sb.Append("[");
- var sawDash = false; // if dash is one of the characters it must be last in the pattern
- foreach (var c in trimChars)
- {
- if (c == '-')
- {
- sawDash = true;
- }
- else
- {
- sb.Append(Regex.Escape(c.ToString()));
- }
- }
- if (sawDash)
+ var characterClass = string.Join("", trimChars.Select(c => (c == '-') ? "\\-" : (c == ']') ? "\\]" : Regex.Escape(c.ToString())).ToArray());
+ if (trimChars.Length > 1)
{
- sb.Append("-");
+ characterClass = "[" + characterClass + "]";
}
- sb.Append("]*");
- return sb.ToString();
+ return characterClass + "*";
}
private BsonValue SerializeValue(BsonSerializationInfo serializationInfo, object value)
View
109 DriverUnitTests/Linq/SelectQueryTests.cs
@@ -4352,6 +4352,113 @@ public void TestWhereSEndsWithAbcNot()
}
[Test]
+ public void TestWhereSIndexOfAnyBC()
+ {
+ var collection = _database.GetCollection("temp");
+ collection.Drop();
+ collection.Insert(new C { S = "bxxx" });
+ collection.Insert(new C { S = "xbxx" });
+ collection.Insert(new C { S = "xxbx" });
+ collection.Insert(new C { S = "xxxb" });
+ collection.Insert(new C { S = "bxbx" });
+ collection.Insert(new C { S = "xbbx" });
+ collection.Insert(new C { S = "xxbb" });
+
+ var query1 =
+ from c in collection.AsQueryable<C>()
+ where c.S.IndexOfAny(new char[] { 'b', 'c' }) == 2
+ select c;
+ Assert.AreEqual(2, Consume(query1));
+
+ var query2 =
+ from c in collection.AsQueryable<C>()
+ where c.S.IndexOfAny(new char[] { 'b', 'c' }, 1) == 2
+ select c;
+ Assert.AreEqual(3, Consume(query2));
+
+ var query3 =
+ from c in collection.AsQueryable<C>()
+ where c.S.IndexOfAny(new char[] { 'b', 'c' }, 1, 1) == 2
+ select c;
+ Assert.AreEqual(0, Consume(query3));
+
+ var query4 =
+ from c in collection.AsQueryable<C>()
+ where c.S.IndexOfAny(new char[] { 'b', 'c' }, 1, 2) == 2
+ select c;
+ Assert.AreEqual(3, Consume(query4));
+ }
+
+ [Test]
+ public void TestWhereSIndexOfAnyBDashCEquals1()
+ {
+ var query = from c in _collection.AsQueryable<C>()
+ where c.S.IndexOfAny(new char[] { 'b', '-', 'c' }) == 1
+ select c;
+
+ var translatedQuery = MongoQueryTranslator.Translate(query);
+ Assert.IsInstanceOf<SelectQuery>(translatedQuery);
+ Assert.AreSame(_collection, translatedQuery.Collection);
+ Assert.AreSame(typeof(C), translatedQuery.DocumentType);
+
+ var selectQuery = (SelectQuery)translatedQuery;
+ Assert.AreEqual("(C c) => (c.S.IndexOfAny(Char[]:{ 'b', '-', 'c' }) == 1)", ExpressionFormatter.ToString(selectQuery.Where));
+ Assert.IsNull(selectQuery.OrderBy);
+ Assert.IsNull(selectQuery.Projection);
+ Assert.IsNull(selectQuery.Skip);
+ Assert.IsNull(selectQuery.Take);
+
+ Assert.AreEqual("{ \"s\" : /^[^b\\-c]{1}[b\\-c]/s }", selectQuery.BuildQuery().ToJson());
+ Assert.AreEqual(1, Consume(query));
+ }
+
+ [Test]
+ public void TestWhereSIndexOfAnyBCStartIndex1Equals1()
+ {
+ var query = from c in _collection.AsQueryable<C>()
+ where c.S.IndexOfAny(new char[] { 'b', '-', 'c' }, 1) == 1
+ select c;
+
+ var translatedQuery = MongoQueryTranslator.Translate(query);
+ Assert.IsInstanceOf<SelectQuery>(translatedQuery);
+ Assert.AreSame(_collection, translatedQuery.Collection);
+ Assert.AreSame(typeof(C), translatedQuery.DocumentType);
+
+ var selectQuery = (SelectQuery)translatedQuery;
+ Assert.AreEqual("(C c) => (c.S.IndexOfAny(Char[]:{ 'b', '-', 'c' }, 1) == 1)", ExpressionFormatter.ToString(selectQuery.Where));
+ Assert.IsNull(selectQuery.OrderBy);
+ Assert.IsNull(selectQuery.Projection);
+ Assert.IsNull(selectQuery.Skip);
+ Assert.IsNull(selectQuery.Take);
+
+ Assert.AreEqual("{ \"s\" : /^.{1}[^b\\-c]{0}[b\\-c]/s }", selectQuery.BuildQuery().ToJson());
+ Assert.AreEqual(1, Consume(query));
+ }
+
+ [Test]
+ public void TestWhereSIndexOfAnyBCStartIndex1Count2Equals1()
+ {
+ var query = from c in _collection.AsQueryable<C>()
+ where c.S.IndexOfAny(new char[] { 'b', '-', 'c' }, 1, 2) == 1
+ select c;
+
+ var translatedQuery = MongoQueryTranslator.Translate(query);
+ Assert.IsInstanceOf<SelectQuery>(translatedQuery);
+ Assert.AreSame(_collection, translatedQuery.Collection);
+ Assert.AreSame(typeof(C), translatedQuery.DocumentType);
+
+ var selectQuery = (SelectQuery)translatedQuery;
+ Assert.AreEqual("(C c) => (c.S.IndexOfAny(Char[]:{ 'b', '-', 'c' }, 1, 2) == 1)", ExpressionFormatter.ToString(selectQuery.Where));
+ Assert.IsNull(selectQuery.OrderBy);
+ Assert.IsNull(selectQuery.Projection);
+ Assert.IsNull(selectQuery.Skip);
+ Assert.IsNull(selectQuery.Take);
+
+ Assert.AreEqual("{ \"s\" : /^.{1}(?=.{2})[^b\\-c]{0}[b\\-c]/s }", selectQuery.BuildQuery().ToJson());
+ Assert.AreEqual(1, Consume(query));
+ }
+
+ [Test]
public void TestWhereSIndexOfB()
{
var collection = _database.GetCollection("temp");
@@ -5068,7 +5175,7 @@ where c.S.TrimStart(' ', '.', '-', '\t').TrimEnd().ToLower().Contains("xyz")
Assert.IsNull(selectQuery.Skip);
Assert.IsNull(selectQuery.Take);
- Assert.AreEqual("{ \"s\" : /^[\\ \\.\\t-]*.*xyz.*\\s*$/is }", selectQuery.BuildQuery().ToJson());
+ Assert.AreEqual("{ \"s\" : /^[\\ \\.\\-\\t]*.*xyz.*\\s*$/is }", selectQuery.BuildQuery().ToJson());
Assert.AreEqual(1, Consume(query));
}
Please sign in to comment.
Something went wrong with that request. Please try again.