mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-04 15:51:37 +00:00
Bug 1258127 - Update the Places schema to track bookmark sync changes. r=mak,rnewman
MozReview-Commit-ID: K27JzgU4KnB --HG-- extra : rebase_source : d5444da8f6d77d66eb174bf09ed3252d5fd55327
This commit is contained in:
parent
b96e085956
commit
564cc476e6
@ -274,10 +274,12 @@ CreateRoot(nsCOMPtr<mozIStorageConnection>& aDBConn,
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
nsresult rv = aDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"INSERT INTO moz_bookmarks "
|
||||
"(type, position, title, dateAdded, lastModified, guid, parent) "
|
||||
"(type, position, title, dateAdded, lastModified, guid, parent, "
|
||||
"syncChangeCounter, syncStatus) "
|
||||
"VALUES (:item_type, :item_position, :item_title,"
|
||||
":date_added, :last_modified, :guid,"
|
||||
"IFNULL((SELECT id FROM moz_bookmarks WHERE parent = 0), 0))"
|
||||
":date_added, :last_modified, :guid, "
|
||||
"IFNULL((SELECT id FROM moz_bookmarks WHERE parent = 0), 0), "
|
||||
"1, :sync_status)"
|
||||
), getter_AddRefs(stmt));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
@ -295,6 +297,9 @@ CreateRoot(nsCOMPtr<mozIStorageConnection>& aDBConn,
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("guid"), aGuid);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("sync_status"),
|
||||
nsINavBookmarksService::SYNC_STATUS_NEW);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = stmt->Execute();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
@ -877,6 +882,13 @@ Database::InitSchema(bool* aDatabaseMigrated)
|
||||
|
||||
// Firefox 52 uses schema version 35.
|
||||
|
||||
if (currentSchemaVersion < 36) {
|
||||
rv = MigrateV36Up();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 53 uses schema version 36.
|
||||
|
||||
// Schema Upgrades must add migration code here.
|
||||
|
||||
rv = UpdateBookmarkRootTitles();
|
||||
@ -927,6 +939,8 @@ Database::InitSchema(bool* aDatabaseMigrated)
|
||||
// moz_bookmarks.
|
||||
rv = mMainConn->ExecuteSimpleSQL(CREATE_MOZ_BOOKMARKS);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mMainConn->ExecuteSimpleSQL(CREATE_MOZ_BOOKMARKS_DELETED);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_BOOKMARKS_PLACETYPE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_BOOKMARKS_PARENTPOSITION);
|
||||
@ -1033,6 +1047,27 @@ Database::CreateBookmarkRoots()
|
||||
|
||||
int64_t mobileRootId = CreateMobileRoot();
|
||||
if (mobileRootId <= 0) return NS_ERROR_FAILURE;
|
||||
{
|
||||
nsCOMPtr<mozIStorageStatement> mobileRootSyncStatusStmt;
|
||||
rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"UPDATE moz_bookmarks SET syncStatus = :sync_status WHERE id = :id"
|
||||
), getter_AddRefs(mobileRootSyncStatusStmt));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
mozStorageStatementScoper mobileRootSyncStatusScoper(
|
||||
mobileRootSyncStatusStmt);
|
||||
|
||||
rv = mobileRootSyncStatusStmt->BindInt32ByName(
|
||||
NS_LITERAL_CSTRING("sync_status"),
|
||||
nsINavBookmarksService::SYNC_STATUS_NEW
|
||||
);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = mobileRootSyncStatusStmt->BindInt64ByName(NS_LITERAL_CSTRING("id"),
|
||||
mobileRootId);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mobileRootSyncStatusStmt->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
@ -1911,6 +1946,52 @@ Database::MigrateV35Up() {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Database::MigrateV36Up() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Add sync status and change counter tracking columns for bookmarks.
|
||||
nsCOMPtr<mozIStorageStatement> syncStatusStmt;
|
||||
nsresult rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT syncStatus FROM moz_bookmarks"
|
||||
), getter_AddRefs(syncStatusStmt));
|
||||
if (NS_FAILED(rv)) {
|
||||
// We default to SYNC_STATUS_UNKNOWN = 0 for existing bookmarks, matching
|
||||
// the bookmark restore behavior. If Sync is set up, we'll update the status
|
||||
// to SYNC_STATUS_NORMAL = 2 before the first post-migration sync.
|
||||
rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"ALTER TABLE moz_bookmarks "
|
||||
"ADD COLUMN syncStatus INTEGER DEFAULT 0 NOT NULL"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> syncChangeCounterStmt;
|
||||
rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT syncChangeCounter FROM moz_bookmarks"
|
||||
), getter_AddRefs(syncChangeCounterStmt));
|
||||
if (NS_FAILED(rv)) {
|
||||
// The change counter starts at 1 for all local bookmarks. It's incremented
|
||||
// for each modification that should trigger a sync, and decremented after
|
||||
// the modified bookmark is uploaded to the server.
|
||||
rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"ALTER TABLE moz_bookmarks "
|
||||
"ADD COLUMN syncChangeCounter INTEGER DEFAULT 1 NOT NULL"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> tombstoneTableStmt;
|
||||
rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT 1 FROM moz_bookmarks_deleted"
|
||||
), getter_AddRefs(tombstoneTableStmt));
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = mMainConn->ExecuteSimpleSQL(CREATE_MOZ_BOOKMARKS_DELETED);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Database::GetItemsWithAnno(const nsACString& aAnnoName, int32_t aItemType,
|
||||
nsTArray<int64_t>& aItemIds)
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
// This is the schema version. Update it at any schema change and add a
|
||||
// corresponding migrateVxx method below.
|
||||
#define DATABASE_SCHEMA_VERSION 35
|
||||
#define DATABASE_SCHEMA_VERSION 36
|
||||
|
||||
// Fired after Places inited.
|
||||
#define TOPIC_PLACES_INIT_COMPLETE "places-init-complete"
|
||||
@ -271,6 +271,7 @@ protected:
|
||||
nsresult MigrateV33Up();
|
||||
nsresult MigrateV34Up();
|
||||
nsresult MigrateV35Up();
|
||||
nsresult MigrateV36Up();
|
||||
|
||||
nsresult UpdateBookmarkRootTitles();
|
||||
|
||||
|
@ -319,6 +319,22 @@ interface nsINavBookmarksService : nsISupports
|
||||
const unsigned short SOURCE_IMPORT = 2;
|
||||
const unsigned short SOURCE_IMPORT_REPLACE = 3;
|
||||
|
||||
/**
|
||||
* Sync status flags.
|
||||
*/
|
||||
// "UNKNOWN" means sync tracking information was lost because the item
|
||||
// was restored from a backup, and needs to be reconciled with the server.
|
||||
// This is set for migrated and restored bookmarks, and changed to "NORMAL"
|
||||
// before upload.
|
||||
const unsigned short SYNC_STATUS_UNKNOWN = 0;
|
||||
// "NEW" means the item has never been synced, so we don't need to write
|
||||
// a tombstone if it's deleted. This is set for all new local bookmarks, and
|
||||
// changed to "NORMAL" before upload.
|
||||
const unsigned short SYNC_STATUS_NEW = 1;
|
||||
// "NORMAL" means the item has been uploaded to the server, and needs a
|
||||
// tombstone if it's deleted.
|
||||
const unsigned short SYNC_STATUS_NORMAL = 2;
|
||||
|
||||
/**
|
||||
* Inserts a child bookmark into the given folder.
|
||||
*
|
||||
|
@ -107,6 +107,34 @@
|
||||
", dateAdded INTEGER" \
|
||||
", lastModified INTEGER" \
|
||||
", guid TEXT" \
|
||||
/* The sync status is determined from the change source. We set this to
|
||||
SYNC_STATUS_NEW = 1 for new local bookmarks, and SYNC_STATUS_NORMAL = 2
|
||||
for bookmarks from other devices. Uploading a local bookmark for the
|
||||
first time changes its status to SYNC_STATUS_NORMAL. For bookmarks
|
||||
restored from a backup, we set SYNC_STATUS_UNKNOWN = 0, indicating that
|
||||
Sync should reconcile them with bookmarks on the server. If Sync is
|
||||
disconnected or never set up, all bookmarks will stay in SYNC_STATUS_NEW.
|
||||
*/ \
|
||||
", syncStatus INTEGER NOT NULL DEFAULT 0" \
|
||||
/* This field is incremented for every bookmark change that should trigger
|
||||
a sync. It's a counter instead of a Boolean so that we can track changes
|
||||
made during a sync, and queue them for the next sync. Changes made by
|
||||
Sync don't bump the counter, to avoid sync loops. If Sync is
|
||||
disconnected, we'll reset the counter to 1 for all bookmarks.
|
||||
*/ \
|
||||
", syncChangeCounter INTEGER NOT NULL DEFAULT 1" \
|
||||
")" \
|
||||
)
|
||||
|
||||
// This table stores tombstones for bookmarks with SYNC_STATUS_NORMAL. We
|
||||
// upload tombstones during a sync, and delete them from this table on success.
|
||||
// If Sync is disconnected, we'll delete all stored tombstones. If Sync is
|
||||
// never set up, we'll never write new tombstones, since all bookmarks will stay
|
||||
// in SYNC_STATUS_NEW.
|
||||
#define CREATE_MOZ_BOOKMARKS_DELETED NS_LITERAL_CSTRING( \
|
||||
"CREATE TABLE moz_bookmarks_deleted (" \
|
||||
" guid TEXT PRIMARY KEY" \
|
||||
", dateRemoved INTEGER NOT NULL DEFAULT 0" \
|
||||
")" \
|
||||
)
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const CURRENT_SCHEMA_VERSION = 35;
|
||||
const CURRENT_SCHEMA_VERSION = 36;
|
||||
const FIRST_UPGRADABLE_SCHEMA_VERSION = 11;
|
||||
|
||||
const NS_APP_USER_PROFILE_50_DIR = "ProfD";
|
||||
|
BIN
toolkit/components/places/tests/migration/places_v36.sqlite
Normal file
BIN
toolkit/components/places/tests/migration/places_v36.sqlite
Normal file
Binary file not shown.
@ -0,0 +1,29 @@
|
||||
add_task(function* setup() {
|
||||
yield setupPlacesDatabase("places_v35.sqlite");
|
||||
});
|
||||
|
||||
add_task(function* database_is_valid() {
|
||||
// Accessing the database for the first time triggers migration.
|
||||
Assert.equal(PlacesUtils.history.databaseStatus,
|
||||
PlacesUtils.history.DATABASE_STATUS_UPGRADED);
|
||||
|
||||
let db = yield PlacesUtils.promiseDBConnection();
|
||||
Assert.equal((yield db.getSchemaVersion()), CURRENT_SCHEMA_VERSION);
|
||||
});
|
||||
|
||||
add_task(function* test_sync_fields() {
|
||||
let db = yield PlacesUtils.promiseDBConnection();
|
||||
let syncFields = yield db.executeCached(`
|
||||
SELECT guid, syncChangeCounter, syncStatus
|
||||
FROM moz_bookmarks`);
|
||||
for (let row of syncFields) {
|
||||
let syncStatus = row.getResultByName("syncStatus");
|
||||
if (syncStatus !== Ci.nsINavBookmarksService.SYNC_STATUS_UNKNOWN) {
|
||||
ok(false, `Wrong sync status for migrated item ${row.getResultByName("guid")}`);
|
||||
}
|
||||
let syncChangeCounter = row.getResultByName("syncChangeCounter");
|
||||
if (syncChangeCounter !== 1) {
|
||||
ok(false, `Wrong change counter for migrated item ${row.getResultByName("guid")}`);
|
||||
}
|
||||
}
|
||||
});
|
@ -22,6 +22,7 @@ support-files =
|
||||
places_v33.sqlite
|
||||
places_v34.sqlite
|
||||
places_v35.sqlite
|
||||
places_v36.sqlite
|
||||
|
||||
[test_current_from_downgraded.js]
|
||||
[test_current_from_v6.js]
|
||||
@ -33,3 +34,4 @@ support-files =
|
||||
[test_current_from_v27.js]
|
||||
[test_current_from_v31.js]
|
||||
[test_current_from_v34.js]
|
||||
[test_current_from_v35.js]
|
||||
|
Loading…
x
Reference in New Issue
Block a user