# # # patch "database.cc" # from [e307170688d9a799c173e9111639a59481539de5] # to [7983bd9c4bc47a044aec8efeb16cc4525c5deb47] # # patch "database.hh" # from [c462132eab925d3c0ce2d1d2c0d5dfe3c8479c6b] # to [94a5eb9d438588b9eabe9d45e9f7910eb7193223] # # patch "migrate_ancestry.cc" # from [c02341580f9e65387807dc8f1ae3874d26e81198] # to [4680079fdb819058bd74e8aa359f10732565e6a0] # # patch "tests/db_data_format_checking/__driver__.lua" # from [c675dbc20a827bb32bd02719a3223e0a0e4001ad] # to [9276846f80cf587d4650260220e87f0c55439d12] # ============================================================ --- database.cc e307170688d9a799c173e9111639a59481539de5 +++ database.cc 7983bd9c4bc47a044aec8efeb16cc4525c5deb47 @@ -183,7 +183,8 @@ namespace enum open_mode { normal_mode = 0, schema_bypass_mode, - format_bypass_mode }; + format_bypass_mode, + cache_bypass_mode }; typedef hashmap::hash_map > parent_id_map; typedef hashmap::hash_map height_map; @@ -221,7 +222,10 @@ private: void open(); void close(); void check_format(); + void check_caches(); + bool table_has_data(string const & name); + // // --== Basic SQL interface and statement caching ==-- // @@ -509,47 +513,28 @@ database::check_is_not_rosterified() void database::check_is_not_rosterified() { - results res; - imp->fetch(res, one_col, any_rows, - query("SELECT 1 FROM rosters LIMIT 1")); - E(res.empty(), origin::user, + E(!imp->table_has_data("rosters"), origin::user, F("this database already contains rosters")); } -void -database_impl::check_format() +bool +database_impl::table_has_data(string const & name) { results res; + fetch(res, one_col, any_rows, query("SELECT 1 FROM " + name + " LIMIT 1")); + return !res.empty(); +} - // Check for manifests, revisions, rosters, and heights. - fetch(res, one_col, any_rows, query("SELECT 1 FROM manifests LIMIT 1")); - bool have_manifests = !res.empty(); - fetch(res, one_col, any_rows, query("SELECT 1 FROM revisions LIMIT 1")); - bool have_revisions = !res.empty(); - fetch(res, one_col, any_rows, query("SELECT 1 FROM rosters LIMIT 1")); - bool have_rosters = !res.empty(); - fetch(res, one_col, any_rows, query("SELECT 1 FROM heights LIMIT 1")); - bool have_heights = !res.empty(); - - - if (!have_manifests) +void +database_impl::check_format() +{ + if (table_has_data("manifests")) { - // Must have been changesetified and rosterified already. - // Or else the database was just created. - // Do we need to regenerate cached data? - E(!have_revisions || (have_rosters && have_heights), - origin::no_fault, - F("database %s lacks some cached data\n" - "run '%s db regenerate_caches' to restore use of this database") - % filename % prog_name); - } - else - { // The rosters and heights tables should be empty. - I(!have_rosters && !have_heights); + I(!table_has_data("rosters") && !table_has_data("heights")); // they need to either changesetify or rosterify. which? - if (have_revisions) + if (table_has_data("revisions")) E(false, origin::no_fault, F("database %s contains old-style revisions\n" "if you are a project leader or doing local testing:\n" @@ -568,6 +553,19 @@ database_impl::check_format() } } +void +database_impl::check_caches() +{ + if (table_has_data("revisions")) + { + E(table_has_data("rosters") && table_has_data("heights"), + origin::no_fault, + F("database %s lacks some cached data\n" + "run '%s db regenerate_caches' to restore use of this database") + % filename % prog_name); + } +} + static void sqlite3_gunzip_fn(sqlite3_context *f, int nargs, sqlite3_value ** args) { @@ -597,7 +595,12 @@ database_impl::sql(enum open_mode mode) check_sql_schema(__sql, filename); if (mode != format_bypass_mode) - check_format(); + { + check_format(); + + if (mode != cache_bypass_mode) + check_caches(); + } } install_functions(); @@ -1210,6 +1213,12 @@ void } void +database::ensure_open_for_cache_reset() +{ + imp->sql(cache_bypass_mode); +} + +void database::ensure_open_for_maintenance() { imp->sql(schema_bypass_mode); ============================================================ --- database.hh c462132eab925d3c0ce2d1d2c0d5dfe3c8479c6b +++ database.hh 94a5eb9d438588b9eabe9d45e9f7910eb7193223 @@ -90,6 +90,7 @@ public: void ensure_open(); void ensure_open_for_format_changes(); + void ensure_open_for_cache_reset(); private: void ensure_open_for_maintenance(); ============================================================ --- migrate_ancestry.cc c02341580f9e65387807dc8f1ae3874d26e81198 +++ migrate_ancestry.cc 4680079fdb819058bd74e8aa359f10732565e6a0 @@ -980,7 +980,7 @@ regenerate_caches(database & db) { P(F("regenerating cached rosters and heights")); - db.ensure_open_for_format_changes(); + db.ensure_open_for_cache_reset(); transaction_guard guard(db); ============================================================ --- tests/db_data_format_checking/__driver__.lua c675dbc20a827bb32bd02719a3223e0a0e4001ad +++ tests/db_data_format_checking/__driver__.lua 9276846f80cf587d4650260220e87f0c55439d12 @@ -8,9 +8,22 @@ mtn_setup() -- be run. This test makes sure that monotone exits with an error if -- given a db that appears to be very old. +-- The database dumps used here are "pre-migrated". They were run +-- through "db migrate" but still need "rosterify" or "changesetify" +-- to be run. But because they've already been migrated to a more +-- recent schema, "db migrate" doesn't know this. So it tries to +-- run regenerate_caches, which will E() about this just like any +-- other command should. +-- +-- FIXME: +-- I suppose this is a good thing to test on its own, but there should +-- really also be a schema_migration_with_changesetify using "real" +-- pre-changeset db dumps, to go with schema_migration_with_rosterify. + check(get("changesetify.db.dumped", "stdin")) check(mtn("-d", "cs-modern.db", "db", "load"), 0, false, false, true) -check(mtn("-d", "cs-modern.db", "db", "migrate"), 0, false, false) +check(mtn("-d", "cs-modern.db", "db", "migrate"), 1, false, true) +check(qgrep("needs to be upgraded", "stderr")) check(mtn("-d", "cs-modern.db", "ls", "keys"), 1, false, false) check(mtn("-d", "cs-modern.db", "ls", "branches"), 1, false, false) @@ -18,7 +31,8 @@ check(mtn("-d", "ro-modern.db", "db", "l check(get("rosterify.db.dumped", "stdin")) check(mtn("-d", "ro-modern.db", "db", "load"), 0, false, false, true) -check(mtn("-d", "ro-modern.db", "db", "migrate"), 0, false, false) +check(mtn("-d", "ro-modern.db", "db", "migrate"), 1, false, true) +check(qgrep("project leader", "stderr")) check(mtn("-d", "ro-modern.db", "ls", "keys"), 1, false, false) check(mtn("-d", "ro-modern.db", "ls", "branches"), 1, false, false)