Add 'deleteRealmIfMigrationNeeded' to configuration to delete a Realm if migration needed (#502)

This commit is contained in:
Ashwin Phatak 2017-10-02 17:22:42 +05:30 committed by GitHub
parent 199210eb68
commit 670f7507f2
5 changed files with 152 additions and 1 deletions

View File

@ -5,6 +5,7 @@ X.Y.Z Release notes
### Enhancements
* Added aggregate functions `min()`, `max()`, `sum()`, and `avg()` to `Realm.Results` and `Realm.List` (#807).
* Added `deleteRealmIfMigrationNeeded` to configuration to delete a Realm if migration needed (#502).
### Bug fixes
* Fixed port conflict between RN >= 0.48 inspector proxy and RPC server used for Chrome debugging (#1294).

View File

@ -296,6 +296,8 @@ Realm.defaultPath;
* - `validate_ssl` - Indicating if SSL certificates must be validated
* - `ssl_trust_certificate_path` - A path where to find trusted SSL certificates
* The `error` callback can take up to four optional arguments: `message`, `isFatal`, `category`, and `code`.
* @property {boolean} [deleteRealmIfMigrationNeeded=false] - Specifies if this Realm should be deleted
* if a migration is needed.
*/
/**

1
lib/index.d.ts vendored
View File

@ -84,6 +84,7 @@ declare namespace Realm {
schema?: ObjectClass[] | ObjectSchema[];
schemaVersion?: number;
sync?: Realm.Sync.SyncConfiguration;
deleteRealmIfMigrationNeeded?: boolean;
}
// object props type

View File

@ -394,6 +394,16 @@ void RealmClass<T>::constructor(ContextType ctx, ObjectType this_object, size_t
config.schema_mode = SchemaMode::ReadOnly;
}
static const String delete_realm_if_migration_needed_string = "deleteRealmIfMigrationNeeded";
ValueType delete_realm_if_migration_needed_value = Object::get_property(ctx, object, delete_realm_if_migration_needed_string);
if (!Value::is_undefined(ctx, delete_realm_if_migration_needed_value) && Value::validated_to_boolean(ctx, delete_realm_if_migration_needed_value, "deleteRealmIfMigrationNeeded")) {
if (config.schema_mode == SchemaMode::ReadOnly) {
throw std::invalid_argument("Cannot set 'deleteRealmIfMigrationNeeded' when 'readOnly' is set.");
}
config.schema_mode = SchemaMode::ResetFile;
}
static const String schema_string = "schema";
ValueType schema_value = Object::get_property(ctx, object, schema_string);
if (!Value::is_undefined(ctx, schema_value)) {
@ -437,6 +447,11 @@ void RealmClass<T>::constructor(ContextType ctx, ObjectType this_object, size_t
ValueType migration_value = Object::get_property(ctx, object, migration_string);
if (!Value::is_undefined(ctx, migration_value)) {
FunctionType migration_function = Value::validated_to_function(ctx, migration_value, "migration");
if (config.schema_mode == SchemaMode::ResetFile) {
throw std::invalid_argument("Cannot include 'migration' when 'deleteRealmIfMigrationNeeded' is set.");
}
config.migration_function = [=](SharedRealm old_realm, SharedRealm realm, realm::Schema&) {
auto old_realm_ptr = new SharedRealm(old_realm);
auto realm_ptr = new SharedRealm(realm);

View File

@ -1025,5 +1025,137 @@ module.exports = {
const realm2 = new Realm(config);
TestCase.assertEqual(realm2.objects('TestObject').length, 0);
realm.close();
},
testRealmDeleteRealmIfMigrationNeededVersionChanged: function() {
const schema = [{
name: 'TestObject',
properties: {
prop0: 'string',
prop1: 'int',
}
}];
var realm = new Realm({schema: schema});
realm.write(function() {
realm.create('TestObject', ['stringValue', 1]);
});
realm.close();
realm = new Realm({schema: schema, deleteRealmIfMigrationNeeded: true, schemaVersion: 1, migration: undefined });
// object should be gone as Realm should get deleted
TestCase.assertEqual(realm.objects('TestObject').length, 0);
// create a new object
realm.write(function() {
realm.create('TestObject', ['stringValue', 1]);
});
realm.close();
var migrationWasCalled = false;
realm = new Realm({schema: schema, deleteRealmIfMigrationNeeded: false, schemaVersion: 2, migration: function(oldRealm, newRealm) {
migrationWasCalled = true;
}});
// migration function should get called as deleteRealmIfMigrationNeeded is false
TestCase.assertEqual(migrationWasCalled, true);
// object should be there because Realm shouldn't get deleted
TestCase.assertEqual(realm.objects('TestObject').length, 1);
realm.close();
},
testRealmDeleteRealmIfMigrationNeededSchemaChanged: function() {
const schema = [{
name: 'TestObject',
properties: {
prop0: 'string',
prop1: 'int',
}
}];
const schema1 = [{
name: 'TestObject',
properties: {
prop0: 'string',
prop1: 'int',
prop2: 'float',
}
}];
const schema2 = [{
name: 'TestObject',
properties: {
prop0: 'string',
prop1: 'int',
prop2: 'float',
prop3: 'double'
}
}];
var realm = new Realm({schema: schema});
realm.write(function() {
realm.create('TestObject', {prop0: 'stringValue', prop1: 1});
});
realm.close();
// change schema
realm = new Realm({schema: schema1, deleteRealmIfMigrationNeeded: true, migration: undefined});
// object should be gone as Realm should get deleted
TestCase.assertEqual(realm.objects('TestObject').length, 0);
// create a new object
realm.write(function() {
realm.create('TestObject', {prop0: 'stringValue', prop1: 1, prop2: 1.0});
});
realm.close();
TestCase.assertThrows(function(e) {
// updating schema without changing schemaVersion OR setting deleteRealmIfMigrationNeeded = true should raise an error
new Realm({schema: schema2, deleteRealmIfMigrationNeeded: false, migration: function(oldRealm, newRealm) {}});
});
var migrationWasCalled = false;
// change schema again, but increment schemaVersion
realm = new Realm({schema: schema2, deleteRealmIfMigrationNeeded: false, schemaVersion: 1, migration: function(oldRealm, newRealm) {
migrationWasCalled = true;
}});
// migration function should get called as deleteRealmIfMigrationNeeded is false
TestCase.assertEqual(migrationWasCalled, true);
// object should be there because Realm shouldn't get deleted
TestCase.assertEqual(realm.objects('TestObject').length, 1);
realm.close();
},
testRealmDeleteRealmIfMigrationNeededIncompatibleConfig: function() {
const schema = [{
name: 'TestObject',
properties: {
prop0: 'string',
prop1: 'int',
}
}];
TestCase.assertThrows(function() {
new Realm({schema: schema, deleteRealmIfMigrationNeeded: true, readOnly: true});
}, "Cannot set 'deleteRealmIfMigrationNeeded' when 'readOnly' is set.")
TestCase.assertThrows(function() {
new Realm({schema: schema, deleteRealmIfMigrationNeeded: true, migration: function(oldRealm, newRealm) {}});
}, "Cannot include 'migration' when 'deleteRealmIfMigrationNeeded' is set.")
},
};