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:
Kit Cambridge 2016-11-20 08:22:02 -08:00
Родитель b96e085956
Коммит 564cc476e6
8 изменённых файлов: 162 добавлений и 5 удалений

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

@ -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";

Двоичные данные
toolkit/components/places/tests/migration/places_v36.sqlite Normal file

Двоичный файл не отображается.

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

@ -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]