Bug 1569516 - Remove very old calendar storage migration code. r=philipp

This commit is contained in:
Geoff Lankow 2019-08-06 19:30:20 +02:00
Родитель 698ca4def8
Коммит c0f1885487
2 изменённых файлов: 1 добавлений и 377 удалений

Просмотреть файл

@ -10,7 +10,6 @@ var { Preferences } = ChromeUtils.import("resource://gre/modules/Preferences.jsm
var { cal } = ChromeUtils.import("resource://calendar/modules/calUtils.jsm");
var REGISTRY_BRANCH = "calendar.registry.";
var DB_SCHEMA_VERSION = 10;
var MAX_INT = Math.pow(2, 31) - 1;
var MIN_INT = -MAX_INT;
@ -40,7 +39,6 @@ calCalendarManager.prototype = {
// calIStartupService:
startup: function(aCompleteListener) {
AddonManager.addAddonListener(gCalendarManagerAddonListener);
this.checkAndMigrateDB();
this.mCache = null;
this.mCalObservers = null;
this.mRefreshTimer = {};
@ -175,227 +173,6 @@ calCalendarManager.prototype = {
}
},
//
// DB migration code begins here
//
upgradeDB: function(oldVersion, db) {
if (oldVersion < 6) {
dump("**** Upgrading calCalendarManager schema to 6\n");
// Schema changes in v6:
//
// - Change all STRING columns to TEXT to avoid SQLite's
// "feature" where it will automatically convert strings to
// numbers (ex: 10e4 -> 10000). See bug 333688.
// Create the new tables.
try {
db.executeSimpleSQL("DROP TABLE cal_calendars_v6; DROP TABLE cal_calendars_prefs_v6;");
} catch (e) {
// We should get exceptions for trying to drop tables
// that don't (shouldn't) exist.
}
db.executeSimpleSQL("CREATE TABLE cal_calendars_v6 " +
"(id INTEGER PRIMARY KEY," +
" type TEXT," +
" uri TEXT);");
db.executeSimpleSQL("CREATE TABLE cal_calendars_prefs_v6 " +
"(id INTEGER PRIMARY KEY," +
" calendar INTEGER," +
" name TEXT," +
" value TEXT);");
// Copy in the data.
let calendarCols = ["id", "type", "uri"];
let calendarPrefsCols = ["id", "calendar", "name", "value"];
db.executeSimpleSQL("INSERT INTO cal_calendars_v6(" + calendarCols.join(",") + ") " +
" SELECT " + calendarCols.join(",") +
" FROM cal_calendars");
db.executeSimpleSQL("INSERT INTO cal_calendars_prefs_v6(" + calendarPrefsCols.join(",") + ") " +
" SELECT " + calendarPrefsCols.join(",") +
" FROM cal_calendars_prefs");
// Delete each old table and rename the new ones to use the
// old tables' names.
let tableNames = ["cal_calendars", "cal_calendars_prefs"];
for (let i in tableNames) {
db.executeSimpleSQL("DROP TABLE " + tableNames[i] + ";" +
"ALTER TABLE " + tableNames[i] + "_v6 " +
" RENAME TO " + tableNames[i] + ";");
}
oldVersion = 8;
}
if (oldVersion < DB_SCHEMA_VERSION) {
dump("**** Upgrading calCalendarManager schema to 9/10\n");
if (db.tableExists("cal_calmgr_schema_version")) {
// Set only once the last time to v10, so the version check works in calendar 0.8.
// In calendar 0.9 and following, the provider itself will check its version
// on initialization and notify the calendar whether it's usable or not.
db.executeSimpleSQL("UPDATE cal_calmgr_schema_version SET version = " + DB_SCHEMA_VERSION + ";");
} else {
// Schema changes in v9:
//
// - Decouple schema version from storage calendar
// Create the new tables.
db.executeSimpleSQL("CREATE TABLE cal_calmgr_schema_version (version INTEGER);");
db.executeSimpleSQL("INSERT INTO cal_calmgr_schema_version VALUES(" + DB_SCHEMA_VERSION + ")");
}
}
},
migrateDB: function(db) {
let selectCalendars = db.createStatement("SELECT * FROM cal_calendars");
let selectPrefs = db.createStatement("SELECT name, value FROM cal_calendars_prefs WHERE calendar = :calendar");
try {
let sortOrder = {};
while (selectCalendars.executeStep()) {
let id = cal.getUUID(); // use fresh uuids
Services.prefs.setCharPref(getPrefBranchFor(id) + "type", selectCalendars.row.type);
Services.prefs.setCharPref(getPrefBranchFor(id) + "uri", selectCalendars.row.uri);
// the former id served as sort position:
sortOrder[selectCalendars.row.id] = id;
// move over prefs:
selectPrefs.params.calendar = selectCalendars.row.id;
while (selectPrefs.executeStep()) {
let name = selectPrefs.row.name.toLowerCase(); // may come lower case, so force it to be
let value = selectPrefs.row.value;
switch (name) {
case "readonly":
Services.prefs.setBoolPref(getPrefBranchFor(id) + "readOnly", value == "true");
break;
case "relaxedmode":
Services.prefs.setBoolPref(getPrefBranchFor(id) + "relaxedMode", value == "true");
break;
case "suppressalarms":
Services.prefs.setBoolPref(getPrefBranchFor(id) + "suppressAlarms", value == "true");
break;
case "disabled":
case "cache.supported":
case "auto-enabled":
case "cache.enabled":
case "calendar-main-in-composite":
case "calendar-main-default":
Services.prefs.setBoolPref(getPrefBranchFor(id) + name, value == "true");
break;
case "backup-time":
case "uniquenum":
// These preference names were migrated due to bug 979262.
Services.prefs.setStringPref(getPrefBranchFor(id) + name + "2", "bignum:" + value);
break;
default: // keep as string
Services.prefs.setStringPref(getPrefBranchFor(id) + name, value);
break;
}
}
selectPrefs.reset();
}
let sortOrderAr = [];
for (let id in sortOrder) {
sortOrderAr.push(sortOrder[id]);
}
Services.prefs.setStringPref("calendar.list.sortOrder", sortOrderAr.join(" "));
flushPrefs();
} finally {
selectPrefs.reset();
selectCalendars.reset();
}
},
checkAndMigrateDB: function() {
let storageSdb = Services.dirsvc.get("ProfD", Ci.nsIFile);
storageSdb.append("storage.sdb");
let db = Services.storage.openDatabase(storageSdb);
db.defaultTransactionType = Ci.mozIStorageConnection.TRANSACTION_EXCLUSIVE;
db.beginTransaction();
try {
if (db.tableExists("cal_calendars_prefs")) {
// Check if we need to upgrade:
let version = this.getSchemaVersion(db);
if (version < DB_SCHEMA_VERSION) {
this.upgradeDB(version, db);
}
this.migrateDB(db);
db.executeSimpleSQL("DROP TABLE cal_calendars; " +
"DROP TABLE cal_calendars_prefs; " +
"DROP TABLE cal_calmgr_schema_version;");
}
if (db.tableExists("cal_calendars")) {
db.rollbackTransaction();
} else {
// create dummy cal_calendars, so previous versions (pre 1.0pre) run into the schema check:
db.createTable("cal_calendars", "id INTEGER");
// let schema checks always fail, we cannot take the shared cal_calendar_schema_version:
db.createTable("cal_calmgr_schema_version", "version INTEGER");
db.executeSimpleSQL("INSERT INTO cal_calmgr_schema_version VALUES(" + (DB_SCHEMA_VERSION + 1) + ")");
db.commitTransaction();
}
} catch (exc) {
db.rollbackTransaction();
throw exc;
} finally {
db.close();
}
},
/**
* @return db schema version
* @exception various, depending on error
*/
getSchemaVersion: function(db) {
let stmt;
let version = null;
let table;
if (db.tableExists("cal_calmgr_schema_version")) {
table = "cal_calmgr_schema_version";
} else {
// Fall back to the old schema table
table = "cal_calendar_schema_version";
}
try {
stmt = db.createStatement("SELECT version FROM " + table + " LIMIT 1");
if (stmt.executeStep()) {
version = stmt.row.version;
}
stmt.reset();
if (version !== null) {
// This is the only place to leave this function gracefully.
return version;
}
} catch (e) {
if (stmt) {
stmt.reset();
}
cal.ERROR("++++++++++++ calMgrGetSchemaVersion() error: " + db.lastErrorString);
Cu.reportError("Error getting calendar schema version! DB Error: " + db.lastErrorString);
throw e;
}
throw new Error(table + " SELECT returned no results");
},
//
// / DB migration code ends here
//
alertAndQuit: function() {
// We want to include the extension name in the error message rather
// than blaming Thunderbird.

Просмотреть файл

@ -6,11 +6,7 @@ var { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm")
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
var { cal } = ChromeUtils.import("resource://calendar/modules/calUtils.jsm");
var {
DB_SCHEMA_VERSION,
getSqlTable,
upgradeDB
} = ChromeUtils.import("resource://calendar/modules/calStorageUpgrade.jsm");
var { upgradeDB } = ChromeUtils.import("resource://calendar/modules/calStorageUpgrade.jsm");
var { CAL_ITEM_FLAG, newDateTime } = ChromeUtils.import("resource://calendar/modules/calStorageHelpers.jsm");
var USECS_PER_SECOND = 1000000;
@ -200,155 +196,6 @@ calStorageCalendar.prototype = {
// open the database
this.mDB = Services.storage.openDatabase(fileURL.file);
upgradeDB(this.mDB);
} else if (this.uri.schemeIs("moz-profile-calendar")) {
// This is an old-style moz-profile-calendar. It requires some
// migration steps.
let localDB = cal.provider.getCalendarDirectory();
localDB.append("local.sqlite");
localDB = Services.storage.openDatabase(localDB);
localDB.defaultTransactionType = Ci.mozIStorageConnection.TRANSACTION_EXCLUSIVE;
// First, we need to check if this is from 0.9, i.e we need to
// migrate from storage.sdb to local.sqlite.
let storageSdb = Services.dirsvc.get("ProfD", Ci.nsIFile);
storageSdb.append("storage.sdb");
this.mDB = Services.storage.openDatabase(storageSdb);
this.mDB.defaultTransactionType = Ci.mozIStorageConnection.TRANSACTION_EXCLUSIVE;
if (this.mDB.tableExists("cal_events")) {
cal.LOG("[calStorageCalendar] Migrating storage.sdb -> local.sqlite");
upgradeDB(this.mDB); // upgrade schema before migating data
let attachStatement;
try {
attachStatement = this.mDB.createStatement("ATTACH DATABASE :file_path AS local_sqlite");
attachStatement.params.file_path = localDB.databaseFile.path;
attachStatement.executeStep();
} catch (exc) {
this.logError("prepareInitDB attachStatement.execute exception", exc);
throw exc;
} finally {
if (attachStatement) {
attachStatement.reset();
}
}
try {
// hold lock on storage.sdb until we've migrated data from storage.sdb:
this.mDB.beginTransaction();
try {
if (this.mDB.tableExists("cal_events")) { // check again (with lock)
// take over data and drop from storage.sdb tables:
for (let table in getSqlTable(DB_SCHEMA_VERSION)) {
if (table.substr(0, 4) != "idx_") {
this.mDB.executeSimpleSQL("CREATE TABLE local_sqlite." + table +
" AS SELECT * FROM " + table +
"; DROP TABLE IF EXISTS " + table);
}
}
this.mDB.commitTransaction();
} else { // migration done in the meantime
this.mDB.rollbackTransaction();
}
} catch (exc) {
this.logError("prepareInitDB storage.sdb migration exception", exc);
this.mDB.rollbackTransaction();
throw exc;
}
} finally {
this.mDB.executeSimpleSQL("DETACH DATABASE local_sqlite");
}
}
// Now that we are through, set the database to the new local.sqlite
// and start the upgraders.
this.mDB = localDB;
upgradeDB(this.mDB);
// Afterwards, we have to migrate the moz-profile-calendars to the
// new moz-storage-calendar schema. This is needed due to bug 479867
// and its regression bug 561735. The first calendar created before
// v19 already has a moz-profile-calendar:// uri without an ?id=
// parameter (the id in the database is 0). We need to migrate this
// special calendar differently.
// WARNING: This is a somewhat fragile process. Great care should be
// taken during future schema upgrades to make sure this still
// works.
this.mDB.beginTransaction();
try {
/**
* Helper function to migrate all tables from one id to the next
*
* @param db The database to use
* @param newCalId The new calendar id to set
* @param oldCalId The old calendar id to look for
*/
let migrateTables = function(db, newCalId, oldCalId) {
let tables = [
"cal_alarms", "cal_attachments", "cal_attendees",
"cal_events", "cal_metadata", "cal_properties",
"cal_recurrence", "cal_relations", "cal_todos"
];
for (let tbl of tables) {
let stmt;
try {
stmt = db.createStatement("UPDATE " + tbl +
" SET cal_id = :cal_id" +
" WHERE cal_id = :old_cal_id");
stmt.params.cal_id = newCalId;
stmt.params.old_cal_id = oldCalId;
stmt.executeStep();
} catch (e) {
// Pass error through to enclosing try/catch block
throw e;
} finally {
if (stmt) {
stmt.reset();
}
}
}
};
let id = 0;
let path = this.uri.pathQueryRef;
let pos = path.indexOf("?id=");
if (pos == -1) {
// For some reason, the first storage calendar before the
// v19 upgrade has cal_id=0. If we still have a
// moz-profile-calendar here, then this is the one and we
// need to move all events with cal_id=0 to this id.
cal.LOG("[calStorageCalendar] Migrating stray cal_id=0 calendar to uuid");
migrateTables(this.mDB, this.id, 0);
this.setProperty("uri", "moz-storage-calendar://");
this.setProperty("old_calendar_id", 0);
this.mDB.commitTransaction();
} else {
// There is an "id" parameter in the uri. This calendar
// has not been migrated to using the uuid as its cal_id.
pos = this.uri.pathQueryRef.indexOf("?id=");
if (pos == -1) {
this.mDB.rollbackTransaction();
} else {
cal.LOG("[calStorageCalendar] Migrating numeric cal_id to uuid");
id = parseInt(path.substr(pos + 4), 10);
migrateTables(this.mDB, this.id, id);
// Now remove the id from the uri to make sure we don't do this
// again. Remember the id, so we can recover in case something
// goes wrong.
this.setProperty("uri", "moz-storage-calendar://");
this.setProperty("old_calendar_id", id);
this.mDB.commitTransaction();
}
}
} catch (exc) {
this.logError("prepareInitDB moz-profile-calendar migration exception", exc);
this.mDB.rollbackTransaction();
throw exc;
}
} else if (this.uri.schemeIs("moz-storage-calendar")) {
// New style uri, no need for migration here
let localDB = cal.provider.getCalendarDirectory();