Skip to content

Commit

Permalink
Merge pull request #418 from realm/ad/feature/linq/cleanup-ToList-#369
Browse files Browse the repository at this point in the history
#369 Cleanup ToList in tests
  • Loading branch information
AndyDentFree committed Mar 4, 2016
2 parents 3280e06 + 6b92593 commit 616f90e
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 50 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Still requires installation from private copy of NuGet download.
* Finish `RealmList.CopyTo` so you can apply `ToList` to related lists (issue #299)
* LINQ simple bool searches work without having to use `== true` (issue #362)
* LINQ ! operator works to negate either simple bool properties or complex expressions (issue #77)
* LINQ Count, Single and First can now be used after a Where expression, eg `realm.All<Owner>().Where(p => p.Name == "Dani").First();` as well as with a lambda expression `realm.All<Owner>().Single( p => p.Name == "Tim");` (#369)
* NuGet now inserts `libwrappers.so` for Android targets using `$(SolutionDir)packages` so it copes with the different relative paths in cross-platform (Xamarin Forms) app templates vs pure Android templates.

0.73.0 Private Beta (2016-02-26)
Expand Down
36 changes: 24 additions & 12 deletions Realm.Shared/linq/RealmResultsVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,25 @@ private static Expression StripQuotes(Expression e)
}


/**
Expressions will typically be in a form:
- with embedded Lambda `Count(p => !p.IsInteresting)`
- at the end of a Where `Where(p => !p.IsInteresting).Where()`
The latter form is handled by recursion where evaluation of Visit will
take us back into VisitMethodCall to evaluate the Where call.
*/
private void RecurseToWhereOrRunLambda(MethodCallExpression m)
{
this.Visit(m.Arguments[0]); // creates the query or recurse to "Where"
if (m.Arguments.Count > 1) {
LambdaExpression lambda = (LambdaExpression)StripQuotes (m.Arguments[1]);
this.Visit (lambda.Body);
}
}


internal override Expression VisitMethodCall(MethodCallExpression m)
{
if (m.Method.DeclaringType == typeof(Queryable)) {
Expand All @@ -64,35 +83,28 @@ internal override Expression VisitMethodCall(MethodCallExpression m)
}
if (m.Method.Name == "Count")
{
this.Visit(m.Arguments[0]); // typically recurse down to a "Where"
RecurseToWhereOrRunLambda(m);
int foundCount = (int)NativeQuery.count(_coreQueryHandle);
return Expression.Constant(foundCount);
}
if (m.Method.Name == "Any")
{
this.Visit(m.Arguments[0]); // typically recurse down to a "Where"
RecurseToWhereOrRunLambda(m);
RowHandle firstRow = NativeQuery.find(_coreQueryHandle, IntPtr.Zero);
bool foundAny = !firstRow.IsInvalid;
return Expression.Constant(foundAny);
}
if (m.Method.Name == "First")
{
// unlike Any, has embedded lambda
this.Visit(m.Arguments[0]); // creates the query
LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1]);
this.Visit(lambda.Body);
RecurseToWhereOrRunLambda(m);
RowHandle firstRow = NativeQuery.find(_coreQueryHandle, IntPtr.Zero);
if (firstRow.IsInvalid)
throw new InvalidOperationException("Sequence contains no matching element");
return Expression.Constant(MakeObject(firstRow));
}
if (m.Method.Name == "Single")
if (m.Method.Name == "Single") // same as First with extra checks
{
// unlike Any, has embedded lambda, so treat it more like a Where
// eg: m {value(Realms.RealmResults`1[IntegrationTests.Person]).Single(p => (p.Latitude > 100))}
this.Visit(m.Arguments[0]); // creates the query
LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1]);
this.Visit(lambda.Body);
RecurseToWhereOrRunLambda(m);
RowHandle firstRow = NativeQuery.find(_coreQueryHandle, IntPtr.Zero);
if (firstRow.IsInvalid)
throw new InvalidOperationException("Sequence contains no matching element");
Expand Down
11 changes: 5 additions & 6 deletions Tests/IntegrationTests.Shared/ObjectIntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ public class ObjectIntegrationTests : PeopleTestsBase
public void SimpleTest()
{
MakeThreePeople ();
var allPeople = _realm.All<Person>().ToList();
Debug.WriteLine("There are " + allPeople.Count() + " in total");
var allPeople = _realm.All<Person>().Count();
Debug.WriteLine($"There are {allPeople} in total");

var interestingPeople = from p in _realm.All<Person>() where p.IsInteresting == true select p;

Expand All @@ -45,17 +45,16 @@ public void CreateObjectTest()
}

// Assert
var allPeople = _realm.All<Person>().ToList();
Assert.That(allPeople.Count, Is.EqualTo(1));
Assert.That(_realm.All<Person>().Count(), Is.EqualTo(1));
}

[Test]
public void ReadAndWriteEqualityTest()
{
// Arrange
MakeThreePeople();
var p1 = _realm.All<Person>().Where(p => p.Score >= 100).ToList()[0];
var p2 = _realm.All<Person>().Where(p => p.Score >= 100).ToList()[0];
var p1 = _realm.All<Person>().First(p => p.Score >= 100);
var p2 = _realm.All<Person>().First(p => p.Score >= 100);
Assert.That(p1.Equals(p2));

// Act
Expand Down
56 changes: 28 additions & 28 deletions Tests/IntegrationTests.Shared/RelationshipTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,17 @@ public void Setup()
[Test]
public void TimHasATopDog()
{
var tim = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim = realm.All<Owner>().First( p => p.Name == "Tim");
Assert.That(tim.TopDog.Name, Is.EqualTo( "Bilbo Fleabaggins"));
}


[Test]
public void TimHasTwoIterableDogs()
{
var tim = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim = realm.All<Owner>().First( p => p.Name == "Tim");
var dogNames = new List<string>();
foreach (var dog in tim.Dogs)
foreach (var dog in tim.Dogs) // using foreach here is deliberately testing that syntax
{
dogNames.Add(dog.Name);
}
Expand All @@ -125,7 +125,7 @@ public void TimHasTwoIterableDogs()
[Test]
public void TimHasTwoIterableDogsListed()
{
var tim = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim = realm.All<Owner>().First( p => p.Name == "Tim");
var dogNames = new List<string>();
var dogList = tim.Dogs.ToList(); // this used to crash - issue 299
foreach (var dog in dogList)
Expand All @@ -139,7 +139,7 @@ public void TimHasTwoIterableDogsListed()
[Test]
public void TimsIterableDogsThrowExceptions()
{
var tim = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim = realm.All<Owner>().First( p => p.Name == "Tim");
Assert.Throws<ArgumentNullException> (() => tim.Dogs.CopyTo (null, 0));
Dog[] copiedDogs = new Dog[2];
Assert.Throws<ArgumentOutOfRangeException> (() => tim.Dogs.CopyTo (copiedDogs, -1));
Expand All @@ -152,27 +152,27 @@ public void TimsIterableDogsThrowExceptions()
[Test]
public void TimRetiredHisTopDog()
{
var tim = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim = realm.All<Owner>().First( p => p.Name == "Tim");
using (var trans = realm.BeginWrite()) {
tim.TopDog = null;
trans.Commit ();
}
var tim2 = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim2 = realm.All<Owner>().First( p => p.Name == "Tim");
Assert.That(tim2.TopDog, Is.Null); // the dog departure was saved
}


[Test]
public void TimAddsADogLater()
{
var tim = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim = realm.All<Owner>().First( p => p.Name == "Tim");
Assert.That(tim.Dogs.Count(), Is.EqualTo(2));
using (var trans = realm.BeginWrite()) {
var dog3 = realm.All<Dog>().Where( p => p.Name == "Maggie Mongrel").ToList().First();
tim.Dogs.Add (dog3);
trans.Commit ();
}
var tim2 = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim2 = realm.All<Owner>().First( p => p.Name == "Tim");
Assert.That(tim2.Dogs.Count(), Is.EqualTo(3));
Assert.That(tim2.Dogs[2].Name, Is.EqualTo("Maggie Mongrel"));
}
Expand All @@ -181,14 +181,14 @@ public void TimAddsADogLater()
[Test]
public void TimAddsADogByInsert()
{
var tim = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim = realm.All<Owner>().Single( p => p.Name == "Tim"); // use Single for a change
Assert.That(tim.Dogs.Count(), Is.EqualTo(2));
using (var trans = realm.BeginWrite()) {
var dog3 = realm.All<Dog>().Where( p => p.Name == "Maggie Mongrel").ToList().First();
tim.Dogs.Insert (1, dog3);
trans.Commit ();
}
var tim2 = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim2 = realm.All<Owner>().Single( p => p.Name == "Tim");
Assert.That(tim2.Dogs.Count(), Is.EqualTo(3));
Assert.That(tim2.Dogs[1].Name, Is.EqualTo("Maggie Mongrel"));
Assert.That(tim2.Dogs[2].Name, Is.EqualTo("Earl Yippington III"));
Expand All @@ -198,20 +198,20 @@ public void TimAddsADogByInsert()
[Test]
public void TimLosesHisDogsByOrder()
{
var tim = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim = realm.All<Owner>().Single( p => p.Name == "Tim");
Assert.That(tim.Dogs.Count(), Is.EqualTo(2));
using (var trans = realm.BeginWrite()) {
tim.Dogs.RemoveAt(0);
trans.Commit ();
}
var tim2 = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim2 = realm.All<Owner>().Single( p => p.Name == "Tim");
Assert.That(tim2.Dogs.Count(), Is.EqualTo(1));
Assert.That(tim2.Dogs[0].Name, Is.EqualTo("Earl Yippington III"));
using (var trans = realm.BeginWrite()) {
tim.Dogs.RemoveAt(0);
trans.Commit ();
}
var tim3 = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim3 = realm.All<Owner>().Single( p => p.Name == "Tim");
Assert.That(tim2.Dogs.Count(), Is.EqualTo(0));
Assert.That(tim3.Dogs.Count(), Is.EqualTo(0)); // reloaded object has same empty related set
}
Expand All @@ -220,28 +220,28 @@ public void TimLosesHisDogsByOrder()
[Test]
public void TimLosesHisDogsInOneClear()
{
var tim = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim = realm.All<Owner>().Single( p => p.Name == "Tim");
Assert.That(tim.Dogs.Count(), Is.EqualTo(2));
using (var trans = realm.BeginWrite()) {
tim.Dogs.Clear();
trans.Commit ();
}
var tim2 = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim2 = realm.All<Owner>().Single( p => p.Name == "Tim");
Assert.That(tim2.Dogs.Count(), Is.EqualTo(0));
}


[Test]
public void TimLosesBilbo()
{
var bilbo = realm.All<Dog>().Where( p => p.Name == "Bilbo Fleabaggins").ToList().First();
var tim = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var bilbo = realm.All<Dog> ().First (p => p.Name == "Bilbo Fleabaggins");
var tim = realm.All<Owner>().Single( p => p.Name == "Tim");
Assert.That(tim.Dogs.Count(), Is.EqualTo(2));
using (var trans = realm.BeginWrite()) {
tim.Dogs.Remove(bilbo);
trans.Commit ();
}
var tim2 = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim2 = realm.All<Owner>().Single( p => p.Name == "Tim");
Assert.That(tim2.Dogs.Count(), Is.EqualTo(1));
Assert.That(tim2.Dogs[0].Name, Is.EqualTo("Earl Yippington III"));
}
Expand All @@ -250,15 +250,15 @@ public void TimLosesBilbo()
[Test]
public void DaniHasNoTopDog()
{
var dani = realm.All<Owner>().Where( p => p.Name == "Dani").ToList().First();
var dani = realm.All<Owner>().Where( p => p.Name == "Dani").First();
Assert.That(dani.TopDog, Is.Null);
}


[Test]
public void DaniHasNoDogs()
{
var dani = realm.All<Owner>().Where( p => p.Name == "Dani").ToList().First();
var dani = realm.All<Owner>().Where( p => p.Name == "Dani").Single();
Assert.That(dani.Dogs.Count(), Is.EqualTo(0)); // ToMany relationships always return a RealmList
int dogsIterated = 0;
foreach (var d in dani.Dogs)
Expand All @@ -272,9 +272,9 @@ public void DaniHasNoDogs()
[Test]
public void TestExceptionsFromEmptyListOutOfRange()
{
var dani = realm.All<Owner>().Where(p => p.Name == "Dani").ToList().First();
var dani = realm.All<Owner>().Where(p => p.Name == "Dani").First();
Assert.Throws<IndexOutOfRangeException>(() => dani.Dogs.RemoveAt(0));
var bilbo = realm.All<Dog>().Where(p => p.Name == "Bilbo Fleabaggins").ToList().First();
var bilbo = realm.All<Dog>().Single(p => p.Name == "Bilbo Fleabaggins");
Dog scratch; // for assignment in following getters
Assert.Throws<IndexOutOfRangeException>(() => dani.Dogs.Insert(-1, bilbo));
Assert.Throws<IndexOutOfRangeException>(() => dani.Dogs.Insert(0, bilbo));
Expand All @@ -285,7 +285,7 @@ public void TestExceptionsFromEmptyListOutOfRange()
[Test]
public void TestExceptionsFromIteratingEmptyList()
{
var dani = realm.All<Owner>().Where(p => p.Name == "Dani").ToList().First();
var dani = realm.All<Owner>().Where(p => p.Name == "Dani").Single();
var iter = dani.Dogs.GetEnumerator();
Assert.IsNotNull(iter);
var movedOnToFirstItem = iter.MoveNext();
Expand All @@ -298,9 +298,9 @@ public void TestExceptionsFromIteratingEmptyList()
[Test]
public void TestExceptionsFromTimsDogsOutOfRange()
{
var tim = realm.All<Owner>().Where( p => p.Name == "Tim").ToList().First();
var tim = realm.All<Owner>().Single( p => p.Name == "Tim");
Assert.Throws<IndexOutOfRangeException>( () => tim.Dogs.RemoveAt(4) );
var bilbo = realm.All<Dog>().Where( p => p.Name == "Bilbo Fleabaggins").ToList().First();
var bilbo = realm.All<Dog>().Single( p => p.Name == "Bilbo Fleabaggins");
Dog scratch; // for assignment in following getters
Assert.Throws<IndexOutOfRangeException>( () => tim.Dogs.Insert(-1, bilbo) );
Assert.Throws<IndexOutOfRangeException>( () => tim.Dogs.Insert(3, bilbo) );
Expand Down Expand Up @@ -406,7 +406,7 @@ public void TestManagingStandaloneThreeLevelRelationship()
}

Assert.That(realm.All<Person>().ToList().Count, Is.EqualTo(5));
Assert.That(realm.All<Person>().Where(p => p.FirstName=="Sally").ToList().Count, Is.EqualTo(2));
Assert.That(realm.All<Person>().Count(p => p.FirstName=="Sally"), Is.EqualTo(2));
}


Expand Down Expand Up @@ -435,7 +435,7 @@ public void TestCircularRelationshipsFromStandaloneTwoStage()
}

Assert.That(realm.All<Person>().ToList().Count, Is.EqualTo(4));
Assert.That(realm.All<Person>().Where(p => p.FirstName=="Sally").ToList().Count, Is.EqualTo(1));
Assert.That(realm.All<Person>().Count(p => p.FirstName=="Sally"), Is.EqualTo(1));
}
}
}
8 changes: 7 additions & 1 deletion Tests/IntegrationTests.Shared/SimpleLINQtests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public void CreateList()
Assert.That(s2[0].Email, Is.EqualTo("john@doe.com"));
Assert.That(s2[1].Email, Is.EqualTo("peter@jameson.com"));

var s3 = _realm.All<Person>().Where(p => p.Email != "").ToList();
var s3 = _realm.All<Person>().Where(p => p.Email != "");
Assert.That(s3.Count(), Is.EqualTo(3));
}

Expand All @@ -49,6 +49,9 @@ public void CountWithNot()
var countSimpleNot = _realm.All<Person>().Where(p => !p.IsInteresting).Count();
Assert.That(countSimpleNot, Is.EqualTo(1));

var countSimpleNot2 = _realm.All<Person>().Count(p => !p.IsInteresting);
Assert.That(countSimpleNot2, Is.EqualTo(1));

var countNotEqual = _realm.All<Person>().Where(p => !(p.Score == 42.42f)).Count();
Assert.That(countNotEqual, Is.EqualTo(2));

Expand All @@ -71,6 +74,9 @@ public void CountFoundItems()

var c3 = _realm.All<Person>().Where(p => p.FirstName=="John").Count();
Assert.That(c3, Is.EqualTo(2));

var c4 = _realm.All<Person>().Count(p => p.FirstName=="John");
Assert.That(c4, Is.EqualTo(2));
}


Expand Down
Loading

0 comments on commit 616f90e

Please sign in to comment.