Permalink
Browse files

Added more unit tests for string IndexOf in LINQ queries and fixed a …

…couple edge cases.
  • Loading branch information...
1 parent 0ed1649 commit 3c814cab2ca00a1a0b2882cb6a08a34e2e299209 rstam committed Apr 11, 2012
Showing with 110 additions and 12 deletions.
  1. +35 −12 Driver/Linq/Translators/SelectQuery.cs
  2. +75 −0 DriverUnitTests/Linq/SelectQueryTests.cs
@@ -750,6 +750,12 @@ private IMongoQuery BuildQuery(Expression expression)
private IMongoQuery BuildStringIndexOfQuery(Expression variableExpression, ExpressionType operatorType, ConstantExpression constantExpression)
{
+ // TODO: support other comparison operators
+ if (operatorType != ExpressionType.Equal)
+ {
+ return null;
+ }
+
if (constantExpression.Type != typeof(int))
{
return null;
@@ -803,51 +809,68 @@ private IMongoQuery BuildStringIndexOfQuery(Expression variableExpression, Expre
string pattern = null;
if (value.GetType() == typeof(char))
{
- var c = Regex.Escape(((char)value).ToString());
+ var escapedChar = Regex.Escape(((char)value).ToString());
if (startIndex == -1)
{
// the regex for: IndexOf(c) == index
// is: /^[^c]{index}c/
- pattern = string.Format("^[^{0}]{{{1}}}{0}", c, index);
+ pattern = string.Format("^[^{0}]{{{1}}}{0}", escapedChar, index);
}
else
{
if (count == -1)
{
// the regex for: IndexOf(c, startIndex) == index
// is: /^.{startIndex}[^c]{index - startIndex}c/
- pattern = string.Format("^.{{{1}}}[^{0}]{{{2}}}{0}", c, startIndex, index - startIndex);
+ pattern = string.Format("^.{{{1}}}[^{0}]{{{2}}}{0}", escapedChar, startIndex, index - startIndex);
}
else
{
- // the regex for: IndexOf(c, startIndex, count) == index
- // is: /^.{startIndex}(?=.{count})[^c]{index - startIndex}c/
- pattern = string.Format("^.{{{1}}}(?=.{{{2}}})[^{0}]{{{3}}}{0}", c, startIndex, count, index - startIndex);
+ if (index >= startIndex + count)
+ {
+ // index is outside of the substring so no match is possible
+ return Query.Exists("_id", false); // matches no documents
+ }
+ else
+ {
+ // 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);
+ }
}
}
}
else if (value.GetType() == typeof(string))
{
- var s = Regex.Escape((string)value);
+ var escapedString = Regex.Escape((string)value);
if (startIndex == -1)
{
// the regex for: IndexOf(s) == index
// is: /^(?!.{0,index - 1}s).{index}s/
- pattern = string.Format("^(?!.{{0,{2}}}{0}).{{{1}}}{0}", s, index, index - 1);
+ pattern = string.Format("^(?!.{{0,{2}}}{0}).{{{1}}}{0}", escapedString, index, index - 1);
}
else
{
if (count == -1)
{
// the regex for: IndexOf(s, startIndex) == index
// is: /^.{startIndex}(?!.{0, index - startIndex - 1}s).{index - startIndex}s/
- pattern = string.Format("^.{{{1}}}(?!.{{0,{2}}}{0}).{{{3}}}{0}", s, startIndex, index - startIndex - 1, index - startIndex);
+ pattern = string.Format("^.{{{1}}}(?!.{{0,{2}}}{0}).{{{3}}}{0}", escapedString, startIndex, index - startIndex - 1, index - startIndex);
}
else
{
- // the regex for: IndexOf(s, startIndex, count) == index
- // is: /^.{startIndex}(?=.{count})(?!.{0,index - startIndex - 1}s).{index - startIndex)s/
- pattern = string.Format("^.{{{1}}}(?=.{{{2}}})(?!.{{0,{3}}}{0}).{{{4}}}{0}", s, startIndex, count, index - startIndex - 1, index - startIndex);
+ var unescapedLength = ((string)value).Length;
+ if (unescapedLength > startIndex + count - index)
+ {
+ // substring isn't long enough to match
+ return Query.Exists("_id", false); // matches no documents
+ }
+ else
+ {
+ // the regex for: IndexOf(s, startIndex, count) == index
+ // is: /^.{startIndex}(?=.{count})(?!.{0,index - startIndex - 1}s).{index - startIndex)s/
+ pattern = string.Format("^.{{{1}}}(?=.{{{2}}})(?!.{{0,{3}}}{0}).{{{4}}}{0}", escapedString, startIndex, count, index - startIndex - 1, index - startIndex);
+ }
}
}
}
@@ -4351,6 +4351,44 @@ public void TestWhereSEndsWithAbcNot()
Assert.AreEqual(4, Consume(query));
}
+ [Test]
+ public void TestWhereSIndexOfB()
+ {
+ 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.IndexOf('b') == 2
+ select c;
+ Assert.AreEqual(2, Consume(query1));
+
+ var query2 =
+ from c in collection.AsQueryable<C>()
+ where c.S.IndexOf('b', 1) == 2
+ select c;
+ Assert.AreEqual(3, Consume(query2));
+
+ var query3 =
+ from c in collection.AsQueryable<C>()
+ where c.S.IndexOf('b', 1, 1) == 2
+ select c;
+ Assert.AreEqual(0, Consume(query3));
+
+ var query4 =
+ from c in collection.AsQueryable<C>()
+ where c.S.IndexOf('b', 1, 2) == 2
+ select c;
+ Assert.AreEqual(3, Consume(query4));
+ }
+
[Test]
public void TestWhereSIndexOfBEquals1()
{
@@ -4420,6 +4458,43 @@ public void TestWhereSIndexOfBStartIndex1Count2Equals1()
Assert.AreEqual(1, Consume(query));
}
+ [Test]
+ public void TestWhereSIndexOfXyz()
+ {
+ var collection = _database.GetCollection("temp");
+ collection.Drop();
+ collection.Insert(new C { S = "xyzaaa" });
+ collection.Insert(new C { S = "axyzaa" });
+ collection.Insert(new C { S = "aaxyza" });
+ collection.Insert(new C { S = "aaaxyz" });
+ collection.Insert(new C { S = "aaaaxy" });
+ collection.Insert(new C { S = "xyzxyz" });
+
+ var query1 =
+ from c in collection.AsQueryable<C>()
+ where c.S.IndexOf("xyz") == 3
+ select c;
+ Assert.AreEqual(1, Consume(query1));
+
+ var query2 =
+ from c in collection.AsQueryable<C>()
+ where c.S.IndexOf("xyz", 1) == 3
+ select c;
+ Assert.AreEqual(2, Consume(query2));
+
+ var query3 =
+ from c in collection.AsQueryable<C>()
+ where c.S.IndexOf("xyz", 1, 4) == 3
+ select c;
+ Assert.AreEqual(0, Consume(query3)); // substring isn't long enough to match
+
+ var query4 =
+ from c in collection.AsQueryable<C>()
+ where c.S.IndexOf("xyz", 1, 5) == 3
+ select c;
+ Assert.AreEqual(2, Consume(query4));
+ }
+
[Test]
public void TestWhereSIndexOfXyzEquals3()
{

0 comments on commit 3c814ca

Please sign in to comment.