Bug 1569516 - Remove very old calendar storage migration code. r=philipp
This commit is contained in:
Родитель
698ca4def8
Коммит
c0f1885487
|
@ -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();
|
||||
|
|
Загрузка…
Ссылка в новой задаче