Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Realm.deleteAll() is trying to delete RealmObjects across module boundaries #5745

Open
jpetitto opened this issue Feb 8, 2018 · 6 comments

Comments

@jpetitto
Copy link

jpetitto commented Feb 8, 2018

I have a project with multiple modules using Realm. I was hoping that I could just call deleteAll() on a Realm for one of the modules, but it seems to be trying to delete RealmObjects from the other modules, leading to a runtime exception.

Expected Results

I'd expect deleteAll() to only delete the RealmObjects within the associated Realm.

Actual Results

When the code runs, I get the following runtime exception when calling deleteAll() on the library Realm instance:

Caused by: io.realm.exceptions.RealmException: 'AppModel' doesn't exist in current schema.
          at io.realm.internal.ColumnIndices.getColumnInfo(ColumnIndices.java:112)
          at io.realm.RealmSchema.getColumnInfo(RealmSchema.java:250)
          at io.realm.ImmutableRealmSchema.get(ImmutableRealmSchema.java:41)
          at io.realm.RealmSchema.getAll(RealmSchema.java:88)
          at io.realm.BaseRealm.deleteAll(BaseRealm.java:602)
          at io.realm.Realm.deleteAll(Realm.java:135)
          at com.johnpetitto.realmbug.MainActivity.lambda$onCreate$1$MainActivity(MainActivity.java:30)
          at com.johnpetitto.realmbug.MainActivity$$Lambda$1.execute(Unknown Source:0)
          at io.realm.Realm.executeTransaction(Realm.java:1394)
          at com.johnpetitto.realmbug.MainActivity.onCreate(MainActivity.java:30)
          at android.app.Activity.performCreate(Activity.java:6998)
          at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1230)
          at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2899)

Steps & Code to Reproduce

I created a sample project to reproduce this. Basically there is an app module and a library module. The library module has a @RealmModule in order to differentiate itself from the app code. Both modules contain a single RealmObject. Here is a repository with the full code.

Code Sample

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Realm.init(this);

    try (Realm realm = Realm.getDefaultInstance()) {
        realm.executeTransaction(r -> r.deleteAll());
    }

    RealmConfiguration libraryConfig = new RealmConfiguration.Builder()
            .deleteRealmIfMigrationNeeded()
            .modules(new LibraryModule())
            .build();

    try (Realm realm = Realm.getInstance(libraryConfig)) {
        realm.executeTransaction(r -> r.deleteAll());
    }
}

Version of Realm and tooling

Realm version(s): 4.3.3

Realm sync feature enabled: no

Android Studio version: 3.0

Which Android version and device: Android 8 on a OnePlus 3T

@Zhuinden
Copy link
Contributor

Zhuinden commented Feb 9, 2018

I would think that currently, Realm.deleteAll() tries to delete the items for all currently existing classes that are in the schema of the existing Realm file.

I'm actually more surprised that

 try (Realm realm = Realm.getInstance(libraryConfig)) {

I would have expected this to have a schema mismatch and delete the Realm because migration was needed, after which it SHOULD allow deleting items. So there could be a bug there with schema caching

@cmelchior
Copy link
Contributor

Hi @jpetitto Thanks for the nice example project. I'm able to reproduce the behaviour and something indeed looks fishy. I'm looking into it.

@cmelchior cmelchior self-assigned this Feb 9, 2018
@cmelchior
Copy link
Contributor

I found the issue(s).

  1. You are re-using the underlying file between the two Realm instances. This means that when you open the library instance, the class "AppModel" is already in there. Currently, we don't treat extra tables as an error as long as they don't conflict with the schema you define.

  2. The problem arises when you call schema.getAll() (which deleteAll() does). This method dynamically tries to load the schema information, but it will ask the Java module for information about all classes it finds including "AppModule", but that doesn't exist since it isn't part of the module, so the method crashes with the exception you see. This kinda conflicts with 1.

I suspect this error can also show up in other ways, e.g. through the Realm.isEmpty() method which will return the wrong result.

I'll need to dig a little further, but it looks like we need to fix schema.findAll() method to only return the classes in the defined schema for typed Realms and everything when using DynamicRealm.

3 workarounds exist right now:

// Manually delete objects of a given type. You need to call this for all types in your module.
realm.delete(LibraryModule.class);

// Use different names for files used by app / libraries
RealmConfiguration libConfig = new RealmConfiguration.Builder()
  .name("library.realm")
  .build()

RealmConfiguration appConfig = new RealmConfiguration.Builder()
  .name("app.realm")
  .build()

// Use DynamicRealm to delete everything
DynamicRealm dynamicRealm = DynamicRealm.getInstance(config);
dynamicRealm.executeTransaction(r -> r.deleteAll());

@cmelchior cmelchior removed their assignment Feb 9, 2018
@Zhuinden
Copy link
Contributor

Zhuinden commented Feb 9, 2018

Oh hey, it'd work with DynamicRealm? that's pretty cool, I didn't think of that.

@jpetitto
Copy link
Author

jpetitto commented Feb 9, 2018

Thanks for investigating this @cmelchior - I like the solution of using separate files for each module. I'm currently manually deleting each model type, which can be a bit error prone if I forget to update it. Glad I could help surface the issue with schema.findAll() and using multiple modules.

@akm0012
Copy link

akm0012 commented Mar 8, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants