Merge `master` into `2.0.x` (#1377)

* Add 'deleteRealmIfMigrationNeeded' to configuration to delete a Realm if migration needed (#502)
* Minor update due to changes in objec store
This commit is contained in:
Kenneth Geisshirt 2017-10-03 13:37:21 +02:00 committed by GitHub
parent 1cabee36df
commit 19d05c2021
5 changed files with 152 additions and 1 deletions

View File

@ -78,6 +78,7 @@ X.Y.Z-rc? Release notes (DATE)
### Enhancements
* Add a callback function used to verify SSL certificates in the sync config.
* 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

@ -282,6 +282,8 @@ Realm.defaultPath;
* This function takes two arguments:
* - `oldRealm` - The Realm before migration is performed.
* - `newRealm` - The Realm that uses the latest `schema`, which should be modified as necessary.
* @property {boolean} [deleteRealmIfMigrationNeeded=false] - Specifies if this Realm should be deleted
* if a migration is needed.
* @property {callback(number, number)} [shouldCompactOnLaunch] - The function called when opening
* a Realm for the first time during the life of a process to determine if it should be compacted
* before being returned to the user. The function takes two arguments:

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

@ -422,6 +422,16 @@ void RealmClass<T>::constructor(ContextType ctx, ObjectType this_object, size_t
config.schema_mode = SchemaMode::Immutable;
}
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::Immutable) {
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)) {
@ -465,6 +475,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

@ -1041,5 +1041,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.")
},
};