From 670f7507f2becaa9080a7bcec54de0f0e314982f Mon Sep 17 00:00:00 2001 From: Ashwin Phatak Date: Mon, 2 Oct 2017 17:22:42 +0530 Subject: [PATCH 1/3] Add 'deleteRealmIfMigrationNeeded' to configuration to delete a Realm if migration needed (#502) --- CHANGELOG.md | 1 + docs/realm.js | 2 + lib/index.d.ts | 1 + src/js_realm.hpp | 15 +++++ tests/js/realm-tests.js | 134 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 152 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1db7a19e..2d33832e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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). diff --git a/docs/realm.js b/docs/realm.js index 63c14ad5..4dade57b 100644 --- a/docs/realm.js +++ b/docs/realm.js @@ -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. */ /** diff --git a/lib/index.d.ts b/lib/index.d.ts index dfc06f31..7a60a894 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -84,6 +84,7 @@ declare namespace Realm { schema?: ObjectClass[] | ObjectSchema[]; schemaVersion?: number; sync?: Realm.Sync.SyncConfiguration; + deleteRealmIfMigrationNeeded?: boolean; } // object props type diff --git a/src/js_realm.hpp b/src/js_realm.hpp index ee3e9daf..c1354064 100644 --- a/src/js_realm.hpp +++ b/src/js_realm.hpp @@ -394,6 +394,16 @@ void RealmClass::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::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); diff --git a/tests/js/realm-tests.js b/tests/js/realm-tests.js index 251e8e8d..29596046 100644 --- a/tests/js/realm-tests.js +++ b/tests/js/realm-tests.js @@ -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.") + }, }; From 284db0b1eecc9897fccb6405c2aa90dc65f188fe Mon Sep 17 00:00:00 2001 From: Brian Munkholm Date: Wed, 4 Oct 2017 07:56:13 +0200 Subject: [PATCH 2/3] Update pull_request_template.md --- .github/pull_request_template.md | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 1836ff6b..9dce6c49 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,20 +1,11 @@ - + ## What, How & Why? + + - - -Reference to the issue(s) addressed by this PR: # ??? - - +This closes # ??? ## ☑️ ToDos From b81a38799024fec539675b14f5a1f1735a087e8b Mon Sep 17 00:00:00 2001 From: blagoev Date: Thu, 5 Oct 2017 13:29:40 +0300 Subject: [PATCH 3/3] 1.13.0 Bump version --- CHANGELOG.md | 2 +- dependencies.list | 2 +- package.json | 2 +- src/RealmJS.xcodeproj/project.pbxproj | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d33832e..4a5ffb28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -X.Y.Z Release notes +1.13.0 Release notes (2017-10-5) ============================================================= ### Breaking changes * None diff --git a/dependencies.list b/dependencies.list index 245f0f18..d18b492f 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,5 +1,5 @@ PACKAGE_NAME=realm-js -VERSION=1.12.0 +VERSION=1.13.0 REALM_CORE_VERSION=2.8.6 REALM_SYNC_VERSION=1.10.5 REALM_OBJECT_SERVER_VERSION=1.8.2 diff --git a/package.json b/package.json index 782e6bdf..0b696b2e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "realm", "description": "Realm is a mobile database: an alternative to SQLite and key-value stores", - "version": "1.12.0", + "version": "1.13.0", "license": "Apache-2.0", "homepage": "https://realm.io", "keywords": [ diff --git a/src/RealmJS.xcodeproj/project.pbxproj b/src/RealmJS.xcodeproj/project.pbxproj index 75cb861b..ee219967 100644 --- a/src/RealmJS.xcodeproj/project.pbxproj +++ b/src/RealmJS.xcodeproj/project.pbxproj @@ -956,7 +956,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1.12.0; + CURRENT_PROJECT_VERSION = 1.13.0; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -1020,7 +1020,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1.12.0; + CURRENT_PROJECT_VERSION = 1.13.0; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO;