diff --git a/CHANGELOG.md b/CHANGELOG.md index af0d058f5e..dab8322b46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ * None. ### Compatibility -* Fileformat: Generates files with format v24. Reads and automatically upgrade from fileformat v10. If you want to upgrade from an earlier file format version you will have to use RealmCore v13.x.y or earlier. +* Fileformat: Generates files with format v25. Reads and automatically upgrade from fileformat v10. If you want to upgrade from an earlier file format version you will have to use RealmCore v13.x.y or earlier. ----------- diff --git a/src/realm/backup_restore.cpp b/src/realm/backup_restore.cpp index 8070642af0..164ece3590 100644 --- a/src/realm/backup_restore.cpp +++ b/src/realm/backup_restore.cpp @@ -34,13 +34,14 @@ using VersionList = BackupHandler::VersionList; using VersionTimeList = BackupHandler::VersionTimeList; // Note: accepted versions should have new versions added at front -const VersionList BackupHandler::accepted_versions_ = {24, 23, 22, 21, 20, 11, 10}; +const VersionList BackupHandler::accepted_versions_ = {25, 24, 23, 22, 21, 20, 11, 10}; // the pair is // we keep backup files in 3 months. static constexpr int three_months = 3 * 31 * 24 * 60 * 60; -const VersionTimeList BackupHandler::delete_versions_{{23, three_months}, {22, three_months}, {21, three_months}, - {20, three_months}, {11, three_months}, {10, three_months}}; +const VersionTimeList BackupHandler::delete_versions_{{24, three_months}, {23, three_months}, {22, three_months}, + {21, three_months}, {20, three_months}, {11, three_months}, + {10, three_months}}; // helper functions diff --git a/src/realm/group.cpp b/src/realm/group.cpp index b6703b3af5..05879f7a87 100644 --- a/src/realm/group.cpp +++ b/src/realm/group.cpp @@ -419,6 +419,7 @@ int Group::read_only_version_check(SlabAlloc& alloc, ref_type top_ref, const std case 0: file_format_ok = (top_ref == 0); break; + case 24: case g_current_file_format_version: file_format_ok = true; break; diff --git a/src/realm/group.hpp b/src/realm/group.hpp index 352c5bd25f..945a28dd58 100644 --- a/src/realm/group.hpp +++ b/src/realm/group.hpp @@ -764,6 +764,9 @@ class Group : public ArrayParent { /// Backlinks in BPlusTree /// Sort order of Strings changed (affects sets and the string index) /// + /// 25 Enhanced layout of NodeHeader to support compression. + /// Integer arrays are stored in a compressed format. + /// /// IMPORTANT: When introducing a new file format version, be sure to review /// the file validity checks in Group::open() and DB::do_open, the file /// format selection logic in @@ -771,7 +774,7 @@ class Group : public ArrayParent { /// upgrade logic in Group::upgrade_file_format(), AND the lists of accepted /// file formats and the version deletion list residing in "backup_restore.cpp" - static constexpr int g_current_file_format_version = 24; + static constexpr int g_current_file_format_version = 25; int get_file_format_version() const noexcept; void set_file_format_version(int) noexcept; diff --git a/src/realm/transaction.cpp b/src/realm/transaction.cpp index 9e93875923..8221d65aa3 100644 --- a/src/realm/transaction.cpp +++ b/src/realm/transaction.cpp @@ -533,7 +533,7 @@ void Transaction::upgrade_file_format(int target_file_format_version) // Be sure to revisit the following upgrade logic when a new file format // version is introduced. The following assert attempt to help you not // forget it. - REALM_ASSERT_EX(target_file_format_version == 24, target_file_format_version); + REALM_ASSERT_EX(target_file_format_version == 25, target_file_format_version); // DB::do_open() must ensure that only supported version are allowed. // It does that by asking backup if the current file format version is @@ -584,6 +584,11 @@ void Transaction::upgrade_file_format(int target_file_format_version) t->migrate_col_keys(); } } + if (current_file_format_version < 25) { + for (auto k : table_keys) { + get_table(k); + } + } // NOTE: Additional future upgrade steps go here. } diff --git a/test/test_upgrade_database.cpp b/test/test_upgrade_database.cpp index ae95d1a02d..dad101ce10 100644 --- a/test/test_upgrade_database.cpp +++ b/test/test_upgrade_database.cpp @@ -36,6 +36,7 @@ #include #include "test.hpp" #include "test_table_helper.hpp" +#include "util/compare_groups.hpp" #include @@ -273,8 +274,8 @@ TEST(Upgrade_Database_11) TableRef foo = g.add_table_with_primary_key("foo", type_Int, "id", false); TableRef bar = g.add_table_with_primary_key("bar", type_String, "name", false); TableRef o = g.add_table("origin"); - auto col1 = o->add_column_link(type_Link, "link1", *foo); - auto col2 = o->add_column_link(type_Link, "link2", *bar); + auto col1 = o->add_column(*foo, "link1"); + auto col2 = o->add_column(*bar, "link2"); for (auto id : ids) { auto obj = foo->create_object_with_primary_key(id); @@ -884,4 +885,107 @@ TEST_IF(Upgrade_Database_23, REALM_MAX_BPNODE_SIZE == 4 || REALM_MAX_BPNODE_SIZE g.write(path); #endif // TEST_READ_UPGRADE_MODE } + +TEST_IF(Upgrade_Database_24, REALM_MAX_BPNODE_SIZE == 4 || REALM_MAX_BPNODE_SIZE == 1000) +{ + std::string path = test_util::get_test_resource_path() + "test_upgrade_database_" + + util::to_string(REALM_MAX_BPNODE_SIZE) + "_24.realm"; + +#if TEST_READ_UPGRADE_MODE + CHECK_OR_RETURN(File::exists(path)); + + SHARED_GROUP_TEST_PATH(temp_copy); + + + // Make a copy of the database so that we keep the original file intact and unmodified + File::copy(path, temp_copy); + auto hist = make_in_realm_history(); + DBOptions options; + options.logger = test_context.logger; + auto sg = DB::create(*hist, temp_copy, options); + auto wt = sg->start_write(); + // rt->to_json(std::cout); + wt->verify(); + + SHARED_GROUP_TEST_PATH(path2); + wt->write(path2); + auto db2 = DB::create(path2); + auto wt2 = db2->start_write(); + CHECK(test_util::compare_groups(*wt, *wt2)); +#else + // NOTE: This code must be executed from an old file-format-version 24 + // core in order to create a file-format-version 25 test file! + + const size_t cnt = 10 * REALM_MAX_BPNODE_SIZE; + + std::vector string_values{ + "white", "yellow", "red", "orange", "green", "blue", "grey", "violet", "purple", "black", + }; + + StringData long_string(R"(1. Jeg ved en lærkerede, +jeg siger ikke mer; +den findes på en hede, +et sted som ingen ser. + +2. I reden er der unger, +og ungerne har dun. +De pipper de har tunger, +og reden er så lun. + +3. Og de to gamle lærker, +de flyver tæt omkring. +Jeg tænker nok de mærker, +jeg gør dem ingenting. + +4. Jeg lurer bag en slåen. +Der står jeg ganske nær. +Jeg rækker mig på tåen +og holder på mit vejr. + +5. For ræven han vil bide +og drengen samle bær. +men ingen skal få vide, +hvor lærkereden er. +)"); + StringData dict_value( + R"({"Seven":7, "Six":6, "Points": [1.25, 4.5, 6.75], "Attributes": {"Height": 202, "Weight": 92}})"); + + Timestamp now(std::chrono::system_clock::now()); + auto now_seconds = now.get_seconds(); + + Group g; + + TableRef t = g.add_table_with_primary_key("table", type_ObjectId, "_id", false); + auto col_int = t->add_column(type_Int, "int"); + auto col_optint = t->add_column(type_Int, "optint", true); + /* auto col_bool = */ t->add_column(type_Bool, "bool"); + auto col_string = t->add_column(type_String, "string"); + /* auto col_binary = */ t->add_column(type_Binary, "binary"); + auto col_mixed = t->add_column(type_Mixed, "any"); + auto col_date = t->add_column(type_Timestamp, "date"); + /* auto col_float = */ t->add_column(type_Float, "float"); + /* auto col_double = */ t->add_column(type_Double, "double"); + /* auto col_decimal = */ t->add_column(type_Decimal, "decimal"); + /* auto col_uuid = */ t->add_column(type_UUID, "uuid"); + + TableRef target = g.add_table_with_primary_key("target", type_Int, "_id", false); + auto col_link = t->add_column(*target, "link"); + + auto target_key = target->create_object_with_primary_key(1).get_key(); + for (size_t i = 0; i < cnt; i++) { + + auto o = t->create_object_with_primary_key(ObjectId::gen()); + o.set(col_int, uint64_t(0xffff) + i); + o.set(col_optint, uint64_t(0xffff) + (i % 10)); + o.set(col_string, string_values[i % string_values.size()]); + o.set(col_date, Timestamp(now_seconds + i, 0)); + o.set(col_link, target_key); + } + auto obj = t->create_object_with_primary_key(ObjectId::gen()); + obj.set_json(col_mixed, dict_value); + obj.set(col_string, long_string); + g.write(path); +#endif // TEST_READ_UPGRADE_MODE +} + #endif // TEST_GROUP diff --git a/test/test_upgrade_database_1000_24.realm b/test/test_upgrade_database_1000_24.realm new file mode 100644 index 0000000000..58e86453c3 Binary files /dev/null and b/test/test_upgrade_database_1000_24.realm differ diff --git a/test/test_upgrade_database_4_24.realm b/test/test_upgrade_database_4_24.realm new file mode 100644 index 0000000000..7d8280b0f5 Binary files /dev/null and b/test/test_upgrade_database_4_24.realm differ