Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* BREAKING CHANGE: DynamicRealm.executeTransaction() now throws IllegalArgumentException instead of silently accepting a null Transaction object.
* Fixed an error occurring during test and connectedCheck of unit test example (#1934).
* Added RealmQuery.isNotEmpty() (#2025). (Thank you @stk1m1)
* Added Realm.clear() and RealmList.removeAllFromRealm() (#1560).
* Improved .so loading by using ReLinker (https://github.com/KeepSafe/ReLinker).
* Improved performance of RealmList#contains() (#897).

Expand Down
12 changes: 11 additions & 1 deletion realm/realm-jni/src/io_realm_internal_LinkView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,14 @@ JNIEXPORT jlong JNICALL Java_io_realm_internal_LinkView_nativeFind
return to_jlong_or_not_found(ndx);
} CATCH_STD()
return -1;
}
}

JNIEXPORT void JNICALL Java_io_realm_internal_LinkView_nativeRemoveAllTargetRows
(JNIEnv *env, jobject, jlong nativeLinkViewPtr) {
TR_ENTER_PTR(nativeLinkViewPtr)
try {
LinkView *lv = LV(nativeLinkViewPtr);
lv->remove_all_target_rows();
} CATCH_STD()
}

12 changes: 10 additions & 2 deletions realm/realm-jni/src/io_realm_internal_LinkView.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

import io.realm.entities.AllTypes;
import io.realm.entities.AnnotationIndexTypes;
import io.realm.entities.Cat;
import io.realm.entities.Dog;
import io.realm.entities.DogPrimaryKey;
import io.realm.entities.Owner;
import io.realm.internal.log.RealmLog;
Expand Down Expand Up @@ -87,6 +89,8 @@ private void populateTestRealm(DynamicRealm realm, int objects) {
allTypes.setFloat(AllTypes.FIELD_FLOAT, 1.234567F + i);
allTypes.setString(AllTypes.FIELD_STRING, "test data " + i);
allTypes.setLong(AllTypes.FIELD_LONG, i);
allTypes.getList(AllTypes.FIELD_REALMLIST).add(realm.createObject(Dog.CLASS_NAME));
allTypes.getList(AllTypes.FIELD_REALMLIST).add(realm.createObject(Dog.CLASS_NAME));
}
realm.commitTransaction();
}
Expand Down Expand Up @@ -748,4 +752,45 @@ public void run() {
.between(AllTypes.FIELD_LONG, 4, 9)
.findFirstAsync();
}

@Test
public void clear_all() {
realm.beginTransaction();
realm.createObject(AllTypes.CLASS_NAME);
DynamicRealmObject cat = realm.createObject(Cat.CLASS_NAME);
DynamicRealmObject owner = realm.createObject(Owner.CLASS_NAME);
owner.setObject("cat", cat);
realm.getSchema().create("TestRemoveAll").addField("Field1", String.class);
realm.createObject("TestRemoveAll");
realm.commitTransaction();

assertEquals(1, realm.where(AllTypes.CLASS_NAME).count());
assertEquals(1, realm.where(Owner.CLASS_NAME).count());
assertEquals(1, realm.where(Cat.CLASS_NAME).count());
assertEquals(1, realm.where("TestRemoveAll").count());

realm.beginTransaction();
realm.clear();
realm.commitTransaction();

assertEquals(0, realm.where(AllTypes.CLASS_NAME).count());
assertEquals(0, realm.where(Owner.CLASS_NAME).count());
assertEquals(0, realm.where(Cat.CLASS_NAME).count());
assertEquals(0, realm.where("TestRemoveAll").count());
assertTrue(realm.isEmpty());
}

@Test
public void realmListRemoveAllFromRealm() {
populateTestRealm(realm, 1);
RealmList<DynamicRealmObject> list = realm.where(AllTypes.CLASS_NAME).findFirst().getList(AllTypes.FIELD_REALMLIST);
assertEquals(2, list.size());

realm.beginTransaction();
list.removeAllFromRealm();
realm.commitTransaction();

assertEquals(0, list.size());
assertEquals(0, realm.where(Dog.CLASS_NAME).count());
}
}
112 changes: 110 additions & 2 deletions realm/realm-library/src/androidTest/java/io/realm/RealmListTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@ public void setUp() throws Exception {

@After
public void tearDown() throws Exception {
testRealm.close();
Realm.deleteRealm(testRealm.getConfiguration());
if (testRealm != null) {
testRealm.close();
Realm.deleteRealm(testRealm.getConfiguration());
}
}

private RealmList<Dog> createNonManagedDogList() {
Expand Down Expand Up @@ -979,4 +981,110 @@ public void testSettingListClearsOldItems() {

assertEquals(1, two.getObjects().size());
}

@Test
public void testRemoveAllFromRealm() {
Owner owner = testRealm.where(Owner.class).findFirst();
RealmList<Dog> dogs = owner.getDogs();
assertEquals(TEST_OBJECTS, dogs.size());

testRealm.beginTransaction();
dogs.removeAllFromRealm();
testRealm.commitTransaction();
assertEquals(0, dogs.size());
assertEquals(0, testRealm.where(Dog.class).count());
}

@Test
public void testRealmRemoveAllNotManagedList() {
Owner owner = testRealm.where(Owner.class).findFirst();
RealmList<Dog> dogs = owner.getDogs();
assertEquals(TEST_OBJECTS, dogs.size());

RealmList<Dog> notManagedDogs = new RealmList<Dog>();
for (Dog dog : dogs) {
notManagedDogs.add(dog);
}

testRealm.beginTransaction();
notManagedDogs.removeAllFromRealm();
testRealm.commitTransaction();
assertEquals(0, dogs.size());
assertEquals(0, notManagedDogs.size());
assertEquals(0, testRealm.where(Dog.class).count());
}

@Test
public void testRealmRemoveAllOutsideTransaction() {
Owner owner = testRealm.where(Owner.class).findFirst();
RealmList<Dog> dogs = owner.getDogs();
try {
dogs.removeAllFromRealm();
fail("removeAllFromRealm should be called in a transaction.");
} catch (IllegalStateException e) {
assertEquals("Changing Realm data can only be done from inside a transaction.", e.getMessage());
}
}

@Test
public void testRemoveAllFromListStandaloneObjectShouldThrow() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this test?

  • IllegalStateException will be thrown if the RealmList is not managed.
  • IllegalStateException will be thrown if the RealmList contains standalone object.

I think we should split this into two tests.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, testRealmRemoveAllNotManagedList already exists and it does not throw the IllegalStateException.

so, this tests IllegalStateException will be thrown if the RealmList contains standalone object.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • "IllegalStateException will be thrown if the RealmList is not managed." This doesn't throw if every object is managed.
    See testRealmRemoveAllNotManagedList
  • "IllegalStateException will be thrown if the RealmList contains standalone object." This is what this test do.
  • A standalone object in a managed RealmList is not possible, so no test case for it.

final RealmList<Dog> list = new RealmList<Dog>();

testRealm.beginTransaction();
Dog dog1 = testRealm.where(Dog.class).findFirst();
testRealm.commitTransaction();
Dog dog2 = new Dog();

list.add(dog1);
list.add(dog2);

testRealm.beginTransaction();
try {
list.removeAllFromRealm();
fail("Cannot remove a list with a standalone object in it!");
} catch (IllegalStateException e) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be an IllegalArgumentException instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the exception is sent from RealmObject which is in a illegal state that it is not managed by Realm.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good point 👍

assertEquals("Object malformed: missing object in Realm. Make sure to instantiate RealmObjects with" +
" Realm.createObject()", e.getMessage());
} finally {
testRealm.cancelTransaction();
}

assertEquals(TEST_OBJECTS, testRealm.where(Dog.class).count());
assertEquals(2, list.size());
}

@Test
public void testRemoveAllFromRealmEmptyList() {
RealmList<Dog> dogs = testRealm.where(Owner.class).findFirst().getDogs();
assertEquals(TEST_OBJECTS, dogs.size());

testRealm.beginTransaction();
dogs.removeAllFromRealm();
testRealm.commitTransaction();
assertEquals(0, dogs.size());
assertEquals(0, testRealm.where(Dog.class).count());

// The dogs is empty now.
testRealm.beginTransaction();
dogs.removeAllFromRealm();
testRealm.commitTransaction();
assertEquals(0, dogs.size());
assertEquals(0, testRealm.where(Dog.class).count());

}

@Test
public void testRemoveAllFromRealmInvalidListShouldThrow() {
RealmList<Dog> dogs = testRealm.where(Owner.class).findFirst().getDogs();
assertEquals(TEST_OBJECTS, dogs.size());
testRealm.close();
testRealm = null;

try {
dogs.removeAllFromRealm();
fail("dogs is invalid and it should throw an exception");
} catch (IllegalStateException e) {
assertEquals("This Realm instance has already been closed, making it unusable.", e.getMessage());
}
}
}
50 changes: 50 additions & 0 deletions realm/realm-library/src/androidTest/java/io/realm/RealmTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2906,4 +2906,54 @@ public void run() {
thread.interrupt();
}
}

@Test
public void testClearAll() {
testRealm.beginTransaction();
testRealm.createObject(AllTypes.class);
testRealm.createObject(Owner.class).setCat(testRealm.createObject(Cat.class));
testRealm.commitTransaction();

assertEquals(1, testRealm.where(AllTypes.class).count());
assertEquals(1, testRealm.where(Owner.class).count());
assertEquals(1, testRealm.where(Cat.class).count());

testRealm.beginTransaction();
testRealm.clear();
testRealm.commitTransaction();

assertEquals(0, testRealm.where(AllTypes.class).count());
assertEquals(0, testRealm.where(Owner.class).count());
assertEquals(0, testRealm.where(Cat.class).count());
assertTrue(testRealm.isEmpty());
}

@Test
public void testClearAllInWrongThreadShouldThrow() {
final CountDownLatch signalTestFinished = new CountDownLatch(1);

Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
testRealm.clear();
fail("testRealm cannot be used in another thread!");
} catch (IllegalStateException ignored) {
signalTestFinished.countDown();
}
}
});
thread.start();

TestHelper.awaitOrFail(signalTestFinished);
}

@Test
public void testClearAllCalledOutsideTransaction() {
try {
testRealm.clear();
fail("clear can only be called in transaction block!");
} catch (IllegalStateException ignored) {
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
import io.realm.RealmObject;

public class Cat extends RealmObject {

public static final String CLASS_NAME = "Cat";

private String name;
private long age;
private float height;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

public class Dog extends RealmObject {

public static final String CLASS_NAME = "Dog";

@Index
private String name;
private long age;
Expand Down
13 changes: 12 additions & 1 deletion realm/realm-library/src/main/java/io/realm/BaseRealm.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import java.io.Closeable;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -539,6 +538,18 @@ <E extends RealmObject> E get(Class<E> clazz, String dynamicClassName, long rowI
return result;
}

/**
* Removes all objects from this Realm.
*
* @throws IllegalStateException if the corresponding Realm is closed or on an incorrect thread.
*/
public void clear() {
checkIfValid();
for (RealmObjectSchema objectSchema : schema.getAll()) {
schema.getTable(objectSchema.getClassName()).clear();
}
}

/**
* Deletes the Realm file defined by the given configuration.
*/
Expand Down
23 changes: 22 additions & 1 deletion realm/realm-library/src/main/java/io/realm/RealmList.java
Original file line number Diff line number Diff line change
Expand Up @@ -263,11 +263,12 @@ public void move(int oldPos, int newPos) {
}

/**
* Removes all elements from this list, leaving it empty.
* Removes all elements from this list, leaving it empty. This method doesn't remove the objects from the Realm.
*
* @throws IllegalStateException if Realm instance has been closed or parent object has been removed.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing whitespace between section and throws

* @see List#isEmpty
* @see List#size
* @see #removeAllFromRealm()
*/
@Override
public void clear() {
Expand Down Expand Up @@ -299,6 +300,26 @@ public E remove(int location) {
}
}

/**
* Removes all elements from this list and delete them from the corresponding Realm. This method can be called on a
* non-managed {@link RealmList} if all of the RealmObjects in the list are managed by Realm.
*
* @throws IllegalStateException if the Realm instance has been closed, the parent object has been removed, the
* method is called in a wrong thread or any RealmObject in the list is not managed by Realm.
* @see #clear()
*/
public void removeAllFromRealm() {
if (managedMode) {
checkValidView();
view.removeAllTargetRows();
} else {
for (RealmObject object : nonManagedList) {
object.removeFromRealm();
}
nonManagedList.clear();
}
}

/**
* Returns the element at the specified location in this list.
*
Expand Down
Loading