Bug 1074817 - Handle content preference downgrades for the timestamp column migration. r=MattN, f=mak, a=lmandel
authorTomasz Kołodziejski <tkolodziejski@mozilla.com>
Thu, 16 Oct 2014 00:36:44 -0700
changeset 223497 311b9fafc1e6113d7655854378fd8dbbb73f6e17
parent 223496 e479d61b8fddf0656c9ebdf5425d4a6eca8f1dcd
child 223498 8cd2d57ee2f6960146c505af329abe6451e6aa8a
push id5
push usergszorc@mozilla.com
push dateWed, 29 Oct 2014 02:51:31 +0000
reviewersMattN, lmandel
bugs1074817
milestone35.0a2
Bug 1074817 - Handle content preference downgrades for the timestamp column migration. r=MattN, f=mak, a=lmandel
toolkit/components/contentprefs/nsContentPrefService.js
--- a/toolkit/components/contentprefs/nsContentPrefService.js
+++ b/toolkit/components/contentprefs/nsContentPrefService.js
@@ -1162,16 +1162,23 @@ ContentPrefService.prototype = {
     aDBFile.remove(false);
 
     let dbConnection = this._dbCreate(aDBService, aDBFile);
 
     return dbConnection;
   },
 
   _dbMigrate: function ContentPrefService__dbMigrate(aDBConnection, aOldVersion, aNewVersion) {
+    /**
+     * Migrations should follow the template rules in bug 1074817 comment 3 which are:
+     * 1. Migration should be incremental and non-breaking.
+     * 2. It should be idempotent because one can downgrade an upgrade again.
+     * On downgrade:
+     * 1. Decrement schema version so that upgrade runs the migrations again.
+     */
     aDBConnection.beginTransaction();
 
     try {
        /**
        * If the schema version is 0, that means it was never set, which means
        * the database was somehow created without the schema being applied, perhaps
        * because the system ran out of disk space (although we check for this
        * in _createDB) or because some other code created the database file without
@@ -1208,17 +1215,24 @@ ContentPrefService.prototype = {
     aDBConnection.executeSimpleSQL("DROP TABLE groupsOld");
   },
 
   _dbMigrate2To3: function ContentPrefService__dbMigrate2To3(aDBConnection) {
     this._dbCreateIndices(aDBConnection);
   },
 
   _dbMigrate3To4: function ContentPrefService__dbMigrate3To4(aDBConnection) {
-    aDBConnection.executeSimpleSQL("ALTER TABLE prefs ADD COLUMN timestamp INTEGER NOT NULL DEFAULT 0");
+    // Add timestamp column if it does not exist yet. This operation is idempotent.
+    try {
+      let stmt = aDBConnection.createStatement("SELECT timestamp FROM prefs");
+      stmt.finalize();
+    } catch (e) {
+      aDBConnection.executeSimpleSQL("ALTER TABLE prefs ADD COLUMN timestamp INTEGER NOT NULL DEFAULT 0");
+    }
+
     // To modify prefs_idx drop it and create again.
     aDBConnection.executeSimpleSQL("DROP INDEX IF EXISTS prefs_idx");
     this._dbCreateIndices(aDBConnection);
   },
 
   _parseGroupParam: function ContentPrefService__parseGroupParam(aGroup) {
     if (aGroup == null)
       return null;