Skip to content

Add migration to add sequence numbers to documents #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ class SQLiteSchema {
* The version of the schema. Increase this by one for each migration added to runMigrations
* below.
*/
static final int VERSION = (Persistence.INDEXING_SUPPORT_ENABLED) ? 7 : 6;
static final int VERSION = 7;
// Remove this constant and increment VERSION to enable indexing support
static final int INDEXING_SUPPORT_VERSION = VERSION + 1;

private final SQLiteDatabase db;

Expand Down Expand Up @@ -99,6 +101,10 @@ void runMigrations(int fromVersion, int toVersion) {
}

if (fromVersion < 7 && toVersion >= 7) {
ensureSequenceNumbers();
}

if (fromVersion < INDEXING_SUPPORT_VERSION && toVersion >= INDEXING_SUPPORT_VERSION) {
Preconditions.checkState(Persistence.INDEXING_SUPPORT_ENABLED);
createLocalDocumentsCollectionIndex();
}
Expand Down Expand Up @@ -245,4 +251,34 @@ private void addTargetCount() {
private void addSequenceNumber() {
db.execSQL("ALTER TABLE target_documents ADD COLUMN sequence_number INTEGER");
}

/**
* Ensures that each entry in the remote document cache has a corresponding sentinel row. Any
* entries that lack a sentinel row are given one with the sequence number set to the highest
* recorded sequence number from the target metadata.
*/
private void ensureSequenceNumbers() {
// Get the current highest sequence number
SQLitePersistence.Query sequenceNumberQuery =
new SQLitePersistence.Query(
db, "SELECT highest_listen_sequence_number FROM target_globals LIMIT 1");
Long boxedSequenceNumber = sequenceNumberQuery.firstValue(c -> c.getLong(0));
hardAssert(boxedSequenceNumber != null, "Missing highest sequence number");

long sequenceNumber = boxedSequenceNumber;
SQLiteStatement tagDocument =
db.compileStatement(
"INSERT INTO target_documents (target_id, path, sequence_number) VALUES (0, ?, ?)");
SQLitePersistence.Query untaggedDocumentsQuery =
new SQLitePersistence.Query(
db,
"SELECT RD.path FROM remote_documents AS RD WHERE NOT EXISTS (SELECT TD.path FROM target_documents AS TD WHERE RD.path = TD.path AND TD.target_id = 0)");
untaggedDocumentsQuery.forEach(
row -> {
tagDocument.clearBindings();
tagDocument.bindString(1, row.getString(0));
tagDocument.bindLong(2, sequenceNumber);
hardAssert(tagDocument.executeInsert() != -1, "Failed to insert a sentinel row");
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,49 @@ private void addMutationBatch(SQLiteDatabase db, int batchId, String uid, String
new Object[] {uid, batchId, write.build().toByteArray()});
}

@Test
public void addsSentinelRows() {
schema.runMigrations(0, 6);

long oldSequenceNumber = 1;
// Set the highest sequence number to this value so that untagged documents
// will pick up this value.
long newSequenceNumber = 2;
db.execSQL(
"UPDATE target_globals SET highest_listen_sequence_number = ?",
new Object[] {newSequenceNumber});

// Set up some documents (we only need the keys)
// For the odd ones, add sentinel rows.
for (int i = 0; i < 10; i++) {
String path = "docs/doc_" + i;
db.execSQL("INSERT INTO remote_documents (path) VALUES (?)", new String[] {path});
if (i % 2 == 1) {
db.execSQL(
"INSERT INTO target_documents (target_id, path, sequence_number) VALUES (0, ?, ?)",
new Object[] {path, oldSequenceNumber});
}
}

schema.runMigrations(6, 7);

// Verify.
new SQLitePersistence.Query(
db, "SELECT path, sequence_number FROM target_documents WHERE target_id = 0")
.forEach(
row -> {
String path = row.getString(0);
long sequenceNumber = row.getLong(1);

int docNum = Integer.parseInt(path.split("_")[1]);
// The even documents were missing sequence numbers, they should now be filled in
// to have the new sequence number. The odd documents should have their
// sequence number unchanged, and so be the old value.
long expected = docNum % 2 == 1 ? oldSequenceNumber : newSequenceNumber;
assertEquals(expected, sequenceNumber);
});
}

private void assertNoResultsForQuery(String query, String[] args) {
Cursor cursor = null;
try {
Expand Down