From c90f3e02109a5e9c276a10c6d1f1446fbc6c03a7 Mon Sep 17 00:00:00 2001 From: "Samuel E. Giddins" Date: Mon, 20 Apr 2015 13:16:30 -0700 Subject: [PATCH] [RLMObjectStore] Automatically migrate required properties to be optional --- object_store.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/object_store.cpp b/object_store.cpp index 7e4c0490..6d605138 100644 --- a/object_store.cpp +++ b/object_store.cpp @@ -29,6 +29,34 @@ using namespace realm; using namespace std; +template +static inline +T get_value(TableRef table, size_t row, size_t column); + +template +static inline +void set_value(TableRef table, size_t row, size_t column, T value); + +template <> +StringData get_value(TableRef table, size_t row, size_t column) { + return table->get_string(column, row); +} + +template <> +void set_value(TableRef table, size_t row, size_t column, StringData value) { + table->set_string(column, row, value); +} + +template <> +BinaryData get_value(TableRef table, size_t row, size_t column) { + return table->get_binary(column, row); +} + +template <> +void set_value(TableRef table, size_t row, size_t column, BinaryData value) { + table->set_binary(column, row, value); +} + const char * const c_metadataTableName = "metadata"; const char * const c_versionColumnName = "version"; const size_t c_versionColumnIndex = 0; @@ -208,6 +236,22 @@ static inline bool property_has_changed(Property &p1, Property &p2) { return p1.type != p2.type || p1.name != p2.name || p1.object_type != p2.object_type || p1.is_nullable != p2.is_nullable; } +static bool property_can_be_migrated_to_nullable(Property &old_property, Property &new_property) { + return old_property.type == new_property.type && + !old_property.is_nullable && new_property.is_nullable && + new_property.name == old_property.name; +} + +template +static void copy_property_to_property(Property &old_property, Property &new_property, TableRef table) { + size_t old_column = old_property.table_column, new_column = new_property.table_column; + size_t count = table->size(); + for (size_t i = 0; i < count; i++) { + T old_value = get_value(table, i, old_column); + set_value(table, i, new_column, old_value); + } +} + // set references to tables on targetSchema and create/update any missing or out-of-date tables // if update existing is true, updates existing tables, otherwise validates existing tables // NOTE: must be called from within write transaction @@ -251,6 +295,20 @@ bool ObjectStore::create_tables(Group *group, ObjectStore::Schema &target_schema target_prop.table_column = table->add_column(DataType(target_prop.type), target_prop.name, target_prop.is_nullable); break; } + + if (current_prop && property_can_be_migrated_to_nullable(*current_prop, target_prop)) { + switch (target_prop.type) { + case PropertyTypeString: + copy_property_to_property(*current_prop, target_prop, table); + break; + case PropertyTypeData: + copy_property_to_property(*current_prop, target_prop, table); + break; + default: + REALM_UNREACHABLE(); + } + } + changed = true; } }