зеркало из https://github.com/mozilla/gecko-dev.git
Bug 888784 - Get rid of dead mozIStorageService code in FormHistory.jsm. r=mak
MozReview-Commit-ID: XLOFLpMsPv --HG-- extra : rebase_source : 2e5974c17f733d1a260f663c4fc778e16065512c
This commit is contained in:
Родитель
11e6bb7968
Коммит
f79e6f625d
|
@ -261,98 +261,6 @@ function makeQueryPredicates(aQueryData, delimiter = " AND ") {
|
|||
}).join(delimiter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Storage statement creation and parameter binding
|
||||
*/
|
||||
|
||||
function makeSearchStatement(aSearchData, aSelectTerms) {
|
||||
let query = "SELECT " + aSelectTerms.join(", ") + " FROM moz_formhistory";
|
||||
let queryTerms = makeQueryPredicates(aSearchData);
|
||||
if (queryTerms) {
|
||||
query += " WHERE " + queryTerms;
|
||||
}
|
||||
|
||||
return dbCreateAsyncStatement(query, aSearchData);
|
||||
}
|
||||
|
||||
function makeAddStatement(aNewData, aNow, aBindingArrays) {
|
||||
let query = "INSERT INTO moz_formhistory " +
|
||||
"(fieldname, value, timesUsed, firstUsed, lastUsed, guid) " +
|
||||
"VALUES (:fieldname, :value, :timesUsed, :firstUsed, :lastUsed, :guid)";
|
||||
|
||||
aNewData.timesUsed = aNewData.timesUsed || 1;
|
||||
aNewData.firstUsed = aNewData.firstUsed || aNow;
|
||||
aNewData.lastUsed = aNewData.lastUsed || aNow;
|
||||
return dbCreateAsyncStatement(query, aNewData, aBindingArrays);
|
||||
}
|
||||
|
||||
function makeBumpStatement(aGuid, aNow, aBindingArrays) {
|
||||
let query = "UPDATE moz_formhistory " +
|
||||
"SET timesUsed = timesUsed + 1, lastUsed = :lastUsed WHERE guid = :guid";
|
||||
let queryParams = {
|
||||
lastUsed: aNow,
|
||||
guid: aGuid,
|
||||
};
|
||||
|
||||
return dbCreateAsyncStatement(query, queryParams, aBindingArrays);
|
||||
}
|
||||
|
||||
function makeRemoveStatement(aSearchData, aBindingArrays) {
|
||||
let query = "DELETE FROM moz_formhistory";
|
||||
let queryTerms = makeQueryPredicates(aSearchData);
|
||||
|
||||
if (queryTerms) {
|
||||
log("removeEntries");
|
||||
query += " WHERE " + queryTerms;
|
||||
} else {
|
||||
log("removeAllEntries");
|
||||
// Not specifying any fields means we should remove all entries. We
|
||||
// won't need to modify the query in this case.
|
||||
}
|
||||
|
||||
return dbCreateAsyncStatement(query, aSearchData, aBindingArrays);
|
||||
}
|
||||
|
||||
function makeUpdateStatement(aGuid, aNewData, aBindingArrays) {
|
||||
let query = "UPDATE moz_formhistory SET ";
|
||||
let queryTerms = makeQueryPredicates(aNewData, ", ");
|
||||
|
||||
if (!queryTerms) {
|
||||
throw Components.Exception("Update query must define fields to modify.",
|
||||
Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
}
|
||||
|
||||
query += queryTerms + " WHERE guid = :existing_guid";
|
||||
aNewData.existing_guid = aGuid;
|
||||
|
||||
return dbCreateAsyncStatement(query, aNewData, aBindingArrays);
|
||||
}
|
||||
|
||||
function makeMoveToDeletedStatement(aGuid, aNow, aData, aBindingArrays) {
|
||||
if (supportsDeletedTable) {
|
||||
let query = "INSERT INTO moz_deleted_formhistory (guid, timeDeleted)";
|
||||
let queryTerms = makeQueryPredicates(aData);
|
||||
|
||||
if (aGuid) {
|
||||
query += " VALUES (:guid, :timeDeleted)";
|
||||
} else {
|
||||
// TODO: Add these items to the deleted items table once we've sorted
|
||||
// out the issues from bug 756701
|
||||
if (!queryTerms) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
query += " SELECT guid, :timeDeleted FROM moz_formhistory WHERE " + queryTerms;
|
||||
}
|
||||
|
||||
aData.timeDeleted = aNow;
|
||||
|
||||
return dbCreateAsyncStatement(query, aData, aBindingArrays);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function generateGUID() {
|
||||
// string like: "{f60d9eac-9421-4abc-8491-8e8322b063d4}"
|
||||
let uuid = uuidService.generateUUID().toString();
|
||||
|
@ -370,115 +278,11 @@ function generateGUID() {
|
|||
return btoa(raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Database creation and access
|
||||
*/
|
||||
|
||||
var _dbConnection = null;
|
||||
XPCOMUtils.defineLazyGetter(this, "dbConnection", function() {
|
||||
let dbFile;
|
||||
|
||||
try {
|
||||
dbFile = Services.dirsvc.get("ProfD", Ci.nsIFile).clone();
|
||||
dbFile.append(DB_FILENAME);
|
||||
log("Opening database at " + dbFile.path);
|
||||
|
||||
_dbConnection = Services.storage.openDatabase(dbFile);
|
||||
dbInit();
|
||||
} catch (e) {
|
||||
if (e.result != Cr.NS_ERROR_FILE_CORRUPTED) {
|
||||
throw e;
|
||||
}
|
||||
dbCleanup(dbFile);
|
||||
_dbConnection = Services.storage.openDatabase(dbFile);
|
||||
dbInit();
|
||||
}
|
||||
|
||||
return _dbConnection;
|
||||
});
|
||||
|
||||
|
||||
var dbStmts = new Map();
|
||||
|
||||
/*
|
||||
* dbCreateAsyncStatement
|
||||
*
|
||||
* Creates a statement, wraps it, and then does parameter replacement
|
||||
*/
|
||||
function dbCreateAsyncStatement(aQuery, aParams, aBindingArrays) {
|
||||
if (!aQuery) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let stmt = dbStmts.get(aQuery);
|
||||
if (!stmt) {
|
||||
log("Creating new statement for query: " + aQuery);
|
||||
stmt = dbConnection.createAsyncStatement(aQuery);
|
||||
dbStmts.set(aQuery, stmt);
|
||||
}
|
||||
|
||||
if (aBindingArrays) {
|
||||
let bindingArray = aBindingArrays.get(stmt);
|
||||
if (!bindingArray) {
|
||||
// first time using a particular statement in update
|
||||
bindingArray = stmt.newBindingParamsArray();
|
||||
aBindingArrays.set(stmt, bindingArray);
|
||||
}
|
||||
|
||||
if (aParams) {
|
||||
let bindingParams = bindingArray.newBindingParams();
|
||||
for (let field in aParams) {
|
||||
bindingParams.bindByName(field, aParams[field]);
|
||||
}
|
||||
bindingArray.addParams(bindingParams);
|
||||
}
|
||||
} else if (aParams) {
|
||||
for (let field in aParams) {
|
||||
stmt.params[field] = aParams[field];
|
||||
}
|
||||
}
|
||||
|
||||
return stmt;
|
||||
}
|
||||
|
||||
var dbMigrate;
|
||||
|
||||
/**
|
||||
* Attempts to initialize the database. This creates the file if it doesn't
|
||||
* exist, performs any migrations, etc.
|
||||
*/
|
||||
function dbInit() {
|
||||
log("Initializing Database");
|
||||
|
||||
if (!_dbConnection.tableExists("moz_formhistory")) {
|
||||
dbCreate();
|
||||
return;
|
||||
}
|
||||
|
||||
// When FormHistory is released, we will no longer support the various schema versions prior to
|
||||
// this release that nsIFormHistory2 once did.
|
||||
let version = _dbConnection.schemaVersion;
|
||||
if (version < 3) {
|
||||
throw Components.Exception("DB version is unsupported.",
|
||||
Cr.NS_ERROR_FILE_CORRUPTED);
|
||||
} else if (version != DB_SCHEMA_VERSION) {
|
||||
dbMigrate(version);
|
||||
}
|
||||
}
|
||||
|
||||
var Migrators = {
|
||||
/*
|
||||
* Updates the DB schema to v3 (bug 506402).
|
||||
* Adds deleted form history table.
|
||||
*/
|
||||
dbMigrateToVersion4() {
|
||||
if (!_dbConnection.tableExists("moz_deleted_formhistory")) {
|
||||
let table = dbSchema.tables.moz_deleted_formhistory;
|
||||
let tSQL = Object.keys(table).map(col => [col, table[col]].join(" ")).join(", ");
|
||||
_dbConnection.createTable("moz_deleted_formhistory", tSQL);
|
||||
}
|
||||
},
|
||||
|
||||
async dbAsyncMigrateToVersion4(conn) {
|
||||
const TABLE_NAME = "moz_deleted_formhistory";
|
||||
let tableExists = await conn.tableExists(TABLE_NAME);
|
||||
|
@ -490,137 +294,6 @@ var Migrators = {
|
|||
},
|
||||
};
|
||||
|
||||
function dbCreate() {
|
||||
log("Creating DB -- tables");
|
||||
for (let name in dbSchema.tables) {
|
||||
let table = dbSchema.tables[name];
|
||||
let tSQL = Object.keys(table).map(col => [col, table[col]].join(" ")).join(", ");
|
||||
log("Creating table " + name + " with " + tSQL);
|
||||
_dbConnection.createTable(name, tSQL);
|
||||
}
|
||||
|
||||
log("Creating DB -- indices");
|
||||
for (let name in dbSchema.indices) {
|
||||
let index = dbSchema.indices[name];
|
||||
let statement = "CREATE INDEX IF NOT EXISTS " + name + " ON " + index.table +
|
||||
"(" + index.columns.join(", ") + ")";
|
||||
_dbConnection.executeSimpleSQL(statement);
|
||||
}
|
||||
|
||||
_dbConnection.schemaVersion = DB_SCHEMA_VERSION;
|
||||
}
|
||||
|
||||
dbMigrate = (oldVersion) => {
|
||||
log("Attempting to migrate from version " + oldVersion);
|
||||
|
||||
if (oldVersion > DB_SCHEMA_VERSION) {
|
||||
log("Downgrading to version " + DB_SCHEMA_VERSION);
|
||||
// User's DB is newer. Sanity check that our expected columns are
|
||||
// present, and if so mark the lower version and merrily continue
|
||||
// on. If the columns are borked, something is wrong so blow away
|
||||
// the DB and start from scratch. [Future incompatible upgrades
|
||||
// should switch to a different table or file.]
|
||||
|
||||
if (!dbAreExpectedColumnsPresent()) {
|
||||
throw Components.Exception("DB is missing expected columns",
|
||||
Cr.NS_ERROR_FILE_CORRUPTED);
|
||||
}
|
||||
|
||||
// Change the stored version to the current version. If the user
|
||||
// runs the newer code again, it will see the lower version number
|
||||
// and re-upgrade (to fixup any entries the old code added).
|
||||
_dbConnection.schemaVersion = DB_SCHEMA_VERSION;
|
||||
return;
|
||||
}
|
||||
|
||||
// Note that migration is currently performed synchronously.
|
||||
_dbConnection.beginTransaction();
|
||||
|
||||
try {
|
||||
for (let v = oldVersion + 1; v <= DB_SCHEMA_VERSION; v++) {
|
||||
this.log("Upgrading to version " + v + "...");
|
||||
Migrators["dbMigrateToVersion" + v]();
|
||||
}
|
||||
} catch (e) {
|
||||
this.log("Migration failed: " + e);
|
||||
this.dbConnection.rollbackTransaction();
|
||||
throw e;
|
||||
}
|
||||
|
||||
_dbConnection.schemaVersion = DB_SCHEMA_VERSION;
|
||||
_dbConnection.commitTransaction();
|
||||
|
||||
log("DB migration completed.");
|
||||
};
|
||||
|
||||
/**
|
||||
* Sanity check to ensure that the columns this version of the code expects
|
||||
* are present in the DB we're using.
|
||||
* @returns {boolean} whether expected columns are present
|
||||
*/
|
||||
function dbAreExpectedColumnsPresent() {
|
||||
for (let name in dbSchema.tables) {
|
||||
let table = dbSchema.tables[name];
|
||||
let query = "SELECT " +
|
||||
Object.keys(table).join(", ") +
|
||||
" FROM " + name;
|
||||
try {
|
||||
let stmt = _dbConnection.createStatement(query);
|
||||
// (no need to execute statement, if it compiled we're good)
|
||||
stmt.finalize();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
log("verified that expected columns are present in DB.");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when database creation fails. Finalizes database statements,
|
||||
* closes the database connection, deletes the database file.
|
||||
* @param {Object} dbFile database file to close
|
||||
*/
|
||||
function dbCleanup(dbFile) {
|
||||
log("Cleaning up DB file - close & remove & backup");
|
||||
|
||||
// Create backup file
|
||||
let backupFile = dbFile.leafName + ".corrupt";
|
||||
Services.storage.backupDatabaseFile(dbFile, backupFile);
|
||||
|
||||
dbClose(false);
|
||||
dbFile.remove(false);
|
||||
}
|
||||
|
||||
function dbClose(aShutdown) {
|
||||
log("dbClose(" + aShutdown + ")");
|
||||
|
||||
if (aShutdown) {
|
||||
sendNotification("formhistory-shutdown", null);
|
||||
}
|
||||
|
||||
// Connection may never have been created if say open failed but we still
|
||||
// end up calling dbClose as part of the rest of dbCleanup.
|
||||
if (!_dbConnection) {
|
||||
return;
|
||||
}
|
||||
|
||||
log("dbClose finalize statements");
|
||||
for (let stmt of dbStmts.values()) {
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
dbStmts = new Map();
|
||||
|
||||
let closed = false;
|
||||
_dbConnection.asyncClose(() => closed = true);
|
||||
|
||||
if (!aShutdown) {
|
||||
Services.tm.spinEventLoopUntil(() => closed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} InsertQueryData
|
||||
* @property {Object} updatedChange
|
||||
|
@ -669,11 +342,6 @@ async function updateFormHistoryWrite(aChanges, aPreparedHandlers) {
|
|||
|
||||
// pass 'now' down so that every entry in the batch has the same timestamp
|
||||
let now = Date.now() * 1000;
|
||||
|
||||
// for each change, we either create and append a new storage statement to
|
||||
// stmts or bind a new set of parameters to an existing storage statement.
|
||||
// stmts and bindingArrays are updated when makeXXXStatement eventually
|
||||
// calls dbCreateAsyncStatement.
|
||||
let queries = [];
|
||||
let notifications = [];
|
||||
let conn = await FormHistory.db;
|
||||
|
|
Загрузка…
Ссылка в новой задаче