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

New migration API #1239

Closed
wants to merge 128 commits into from
Closed

New migration API #1239

wants to merge 128 commits into from

Conversation

cmelchior
Copy link
Contributor

This depends on #1200

This PR adds the new Migration API. It introduces a breaking change as the Migration interface has changed. It also introduces 2 new classes: RealmSchema and RealmObjectSchema. The interface for those methods are below and should hopefully be mostly self explanatory (that was the whole point :) )

// New interface for writing migration blocks
public interface RealmMigration {
  void migrate(RealmSchema schema, long oldVersion, long newVersion);
}

// Public methods in RealmSchema
public interface RealmSchemaInterface {
    RealmObjectSchema getClass(String className);
    RealmObjectSchema addClass(String className);
    void removeClass(String className);
    RealmObjectSchema renameClass(String oldName, String newName);
}

// Public methods in RealmObjectSchema
public interface RealmObjectSchemaInterface {
    RealmObjectSchema addString(String fieldName);
    RealmObjectSchema addString(String fieldName, Set<RealmModifier> modifiers);
    RealmObjectSchema addShort(String fieldName);
    RealmObjectSchema addShort(String fieldName, Set<RealmModifier> modifiers);
    RealmObjectSchema addInt(String fieldName);
    RealmObjectSchema addInt(String fieldName, Set<RealmModifier> modifiers);
    RealmObjectSchema addLong(String fieldName);
    RealmObjectSchema addLong(String fieldName, Set<RealmModifier> modifiers);
    RealmObjectSchema addBoolean(String fieldName);
    RealmObjectSchema addBoolean(String fieldName, Set<RealmModifier> modifiers);
    RealmObjectSchema addByteArray(String fieldName);
    RealmObjectSchema addByteArray(String fieldName, Set<RealmModifier> modifiers);
    RealmObjectSchema addFloat(String fieldName);
    RealmObjectSchema addFloat(String fieldName, Set<RealmModifier> modifiers);
    RealmObjectSchema addDouble(String fieldName);
    RealmObjectSchema addDouble(String fieldName, Set<RealmModifier> modifiers);
    RealmObjectSchema addDate(String fieldName);
    RealmObjectSchema addDate(String fieldName, Set<RealmModifier> modifiers);
    RealmObjectSchema addObject(String fieldName, RealmObjectSchema objectSchema);
    RealmObjectSchema addList(String fieldName, RealmObjectSchema objectSchema);
    RealmObjectSchema removeField(String fieldName);
    RealmObjectSchema renameField(String currentFieldName, String newFieldName);
    RealmObjectSchema addIndex(String fieldName);
    RealmObjectSchema removeIndex(String fieldName);
    RealmObjectSchema addPrimaryKey(String fieldName);
    RealmObjectSchema setNonNullable(String fieldName); // Not supported yet
    RealmObjectSchema setNullable(String fieldName); // Not supported yet
    boolean hasPrimaryKey();
    boolean hasIndex(String fieldName);
    RealmObjectSchema removePrimaryKey();
    DynamicRealmObject createObject();
    DynamicRealmObject createObject(Object primaryKeyValue);
    DynamicRealmObject forEach(RealmSchemaObject.Iterator iterator);
}

// Example of usage
public class Migration implements RealmMigration {

    @Override
    public void migrate(RealmSchema schema, long oldVersion, long newVersion) {
        /*
            // Version 0
            class Person
                String fullName;
                String lastName;
                int    age;
            // Version 1
            class Person
                String fullName;        // combine firstName and lastName into single field
                int age;
        */
        if (oldVersion == 0) {
            schema.getClass("Person")
                    .addString("fullName")
                    .forEach(new RealmObjectSchema.Iterator() {
                        @Override
                        public void next(DynamicRealmObject obj) {
                            obj.setString("fullName", obj.getString("firstName") + " " + obj.getString("lastName"));
                        }
                    })
                    .removeField("firstName")
                    .removeField("lastName");
            oldVersion++;
        }

        /*
            // Version 2
            class Pet                   // add a new model class
                String name;
                String type;
            class Person
                String fullName;
                int age;
                RealmList<Pet> pets;    // add a RealmList field
        */
        if (oldVersion == 1) {

            final RealmObjectSchema petSchema = schema.addClass("Pet")
                    .addString("name")
                    .addString("type");

            schema.getClass("Person")
                    .addList("pets", petSchema)
                    .forEach(new RealmObjectSchema.Iterator() { // TODO Should we add query support now?
                        @Override
                        public void next(DynamicRealmObject obj) {
                            if (obj.getString("fullName").equals("JP McDonald")) {
                                DynamicRealmObject pet = petSchema.createObject();
                                pet.setString("name", "Jimbo");
                                pet.setString("type", "dog");
                                obj.getList("pets").add(pet);
                            }
                        }
                    });
            oldVersion++;
        }

        /*
            // Version 3
            class Pet
                @Index
                String name;            // name is indexed
                int type;               // type becomes int
            class Person
                String fullName;
                RealmList<Pet> pets;    // age and pets re-ordered
                int age;
        */
        if (oldVersion == 2) {
            schema.getClass("Pet")
                    .addIndex("name")
                    .addInt("typeTmp")
                    .forEach(new RealmObjectSchema.Iterator() {
                        @Override
                        public void next(DynamicRealmObject obj) {
                            String type = obj.getString("type");
                            if (type.equals("dog")) {
                                obj.setInt("typeTmp", 1);
                            } else if (type.equals("cat")) {
                                obj.setInt("typeTmp", 2);
                            } else if (type.equals("hamster")) {
                                obj.setInt("typeTmp", 3);
                            }
                        }
                    })
                    .removeField("type")
                    .renameField("typeTmp", "type");

            // TODO 4 instructions to change a type, is that acceptable? But the alternative would be an
            // API explosion or to expose something like a "RealmField" which would mean we would have to expose
            // the internal Realm types
            // schema.addField(new RealmField("type", ColumnType.INTEGER))
            oldVersion++;
        }
    }
}

Missing:

  • JavaDoc
  • Unit tests
  • Feedback on missing methods for manipulating schema
  • Feedback from Cocoa
  • Add Null support
  • Class iterator: forEach, Java8 stream/RxJava like

Conflicts:
	realm/src/androidTest/java/io/realm/RealmMigrationTests.java
Conflicts:
	realm/src/androidTest/java/io/realm/RealmMigrationTests.java
	realm/src/main/java/io/realm/Realm.java
	realm/src/main/java/io/realm/RealmMigration.java
	realm/src/main/java/io/realm/internal/Group.java
Conflicts:
	examples/realmModuleExample/app/src/main/java/io/realm/examples/appmodules/model/Spider.java
	realm/src/androidTest/java/io/realm/RealmConfigurationTest.java
	realm/src/main/java/io/realm/Realm.java
	realm/src/main/java/io/realm/internal/migration/MigrationController.java
	realm/src/main/java/io/realm/internal/migration/SetVersionNumberMigration.java
commit c67825e5541d33b1664b62ee7816d9a810f09ad4
Author: Christian Melchior <christian@ilios.dk>
Date:   Wed Jun 17 09:25:32 2015 +0200

    Unit test made more readable.

commit f5cc85b
Author: Christian Melchior <christian@ilios.dk>
Date:   Tue Jun 16 22:36:41 2015 +0200

    Move error checking to JNI

commit e38411d
Author: Christian Melchior <christian@ilios.dk>
Date:   Mon Jun 15 16:33:41 2015 +0200

    Split Row into checked and unchecked version.

commit b0566e0
Merge: 77fb8ac e6256c0
Author: Christian Melchior <christian@ilios.dk>
Date:   Fri Jun 12 15:09:57 2015 +0200

    Merge branch 'cm-dynamic-api' of https://github.com/realm/realm-java into cm-dynamic-api

commit 77fb8ac
Author: Christian Melchior <christian@ilios.dk>
Date:   Fri Jun 12 15:09:35 2015 +0200

    Newline after method

commit e6256c0
Author: Christian Melchior <christian@ilios.dk>
Date:   Fri Jun 12 15:08:42 2015 +0200

    Duplicate new lines

commit 84bf1a2
Author: Christian Melchior <christian@ilios.dk>
Date:   Fri Jun 12 15:07:22 2015 +0200

    PR feedback

commit 48321fc
Merge: 989507c 5094622
Author: Christian Melchior <christian@ilios.dk>
Date:   Fri Jun 12 14:59:03 2015 +0200

    Merge branch 'master' into cm-dynamic-api

commit 989507c
Author: Christian Melchior <christian@ilios.dk>
Date:   Wed Jun 10 10:15:34 2015 +0200

    Renamed column -> field. Added constants. Other small fixes.

commit c138313
Merge: 46464cf e24c90a
Author: Christian Melchior <christian@ilios.dk>
Date:   Tue Jun 9 15:20:49 2015 +0200

    Merge branch 'master' into cm-dynamic-api

commit 46464cf
Author: Christian Melchior <christian@ilios.dk>
Date:   Tue Jun 9 15:20:19 2015 +0200

    Added dynamic object/list + tests.
Conflicts:
	realm-jni/src/io_realm_internal_CheckedRow.cpp
	realm-jni/src/io_realm_internal_CheckedRow.h
	realm-jni/src/io_realm_internal_UncheckedRow.cpp
	realm/src/androidTest/java/io/realm/internal/JNIRowTest.java
	realm/src/main/java/io/realm/Realm.java
	realm/src/main/java/io/realm/internal/CheckedRow.java
	realm/src/main/java/io/realm/internal/LinkView.java
	realm/src/main/java/io/realm/internal/Row.java
	realm/src/main/java/io/realm/internal/Table.java
Conflicts:
	realm/src/main/java/io/realm/RealmQuery.java
	realm/src/main/java/io/realm/internal/TableView.java
Conflicts:
	realm/src/main/java/io/realm/Realm.java
	realm/src/main/java/io/realm/dynamic/DynamicRealmObject.java
Conflicts:
	realm/src/androidTest/java/io/realm/RealmTest.java
	realm/src/main/java/io/realm/BaseRealm.java
	realm/src/main/java/io/realm/DynamicRealmObject.java
	realm/src/main/java/io/realm/Realm.java
	realm/src/main/java/io/realm/RealmQuery.java
	realm/src/main/java/io/realm/internal/SharedGroup.java
…Refactored RealmResults to use factory constructors.
Conflicts:
	realm/src/main/java/io/realm/BaseRealm.java
Conflicts:
	realm/src/main/java/io/realm/RealmQuery.java
Conflicts:
	realm/src/androidTest/java/io/realm/RealmMigrationTests.java
	realm/src/main/java/io/realm/Realm.java
	realm/src/main/java/io/realm/RealmMigration.java
	realm/src/main/java/io/realm/internal/Group.java
	realm/src/main/java/io/realm/internal/Table.java
@cmelchior
Copy link
Contributor Author

This is being superseded by a new PR against the Dynamic/Migration feature branch instead of against master.

@cmelchior cmelchior closed this Oct 26, 2015
@cmelchior cmelchior removed the P1 label Oct 26, 2015
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 16, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants