Merge branch 'readonly-p4-donut' into donut
This commit is contained in:
commit
30eb9bb948
|
@ -79,9 +79,11 @@ public class LocalStore extends Store {
|
|||
* 20 1.5 Added content_id column to attachments table.
|
||||
* 21 - Added remote_store_data table
|
||||
* 22 - Added store_flag_1 and store_flag_2 columns to messages table.
|
||||
* 23 - Added flag_downloaded_full, flag_downloaded_partial, flag_deleted
|
||||
* columns to message table.
|
||||
*/
|
||||
|
||||
private static final int DB_VERSION = 22;
|
||||
private static final int DB_VERSION = 23;
|
||||
|
||||
private static final Flag[] PERMANENT_FLAGS = { Flag.DELETED, Flag.X_DESTROYED, Flag.SEEN };
|
||||
|
||||
|
@ -144,7 +146,8 @@ public class LocalStore extends Store {
|
|||
"to_list TEXT, cc_list TEXT, bcc_list TEXT, reply_to_list TEXT, " +
|
||||
"html_content TEXT, text_content TEXT, attachment_count INTEGER, " +
|
||||
"internal_date INTEGER, message_id TEXT, store_flag_1 INTEGER, " +
|
||||
"store_flag_2 INTEGER)");
|
||||
"store_flag_2 INTEGER, flag_downloaded_full INTEGER," +
|
||||
"flag_downloaded_partial INTEGER, flag_deleted INTEGER)");
|
||||
|
||||
mDb.execSQL("DROP TABLE IF EXISTS attachments");
|
||||
mDb.execSQL("CREATE TABLE attachments (id INTEGER PRIMARY KEY, message_id INTEGER,"
|
||||
|
@ -194,6 +197,26 @@ public class LocalStore extends Store {
|
|||
mDb.execSQL("ALTER TABLE messages ADD COLUMN store_flag_2 INTEGER;");
|
||||
mDb.setVersion(22);
|
||||
}
|
||||
if (oldVersion < 23) {
|
||||
/**
|
||||
* Upgrade 22 to 23: add flag_downloaded_full & flag_downloaded_partial
|
||||
* and flag_deleted columns to message table *and upgrade existing messages*.
|
||||
*/
|
||||
mDb.beginTransaction();
|
||||
try {
|
||||
mDb.execSQL(
|
||||
"ALTER TABLE messages ADD COLUMN flag_downloaded_full INTEGER;");
|
||||
mDb.execSQL(
|
||||
"ALTER TABLE messages ADD COLUMN flag_downloaded_partial INTEGER;");
|
||||
mDb.execSQL(
|
||||
"ALTER TABLE messages ADD COLUMN flag_deleted INTEGER;");
|
||||
migrateMessageFlags();
|
||||
mDb.setVersion(23);
|
||||
mDb.setTransactionSuccessful();
|
||||
} finally {
|
||||
mDb.endTransaction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mDb.getVersion() != DB_VERSION) {
|
||||
|
@ -229,6 +252,52 @@ public class LocalStore extends Store {
|
|||
+ "DELETE FROM remote_store_data WHERE old.id = folder_id; "
|
||||
+ "END;");
|
||||
}
|
||||
|
||||
/**
|
||||
* When upgrading from 22 to 23, we have to move any flags "X_DOWNLOADED_FULL" or
|
||||
* "X_DOWNLOADED_PARTIAL" or "DELETED" from the old string-based storage to their own columns.
|
||||
*
|
||||
* Note: Caller should open a db transaction around this
|
||||
*/
|
||||
private void migrateMessageFlags() {
|
||||
Cursor cursor = mDb.query("messages",
|
||||
new String[] { "id", "flags" },
|
||||
null, null, null, null, null);
|
||||
try {
|
||||
int columnId = cursor.getColumnIndexOrThrow("id");
|
||||
int columnFlags = cursor.getColumnIndexOrThrow("flags");
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
String oldFlags = cursor.getString(columnFlags);
|
||||
ContentValues values = new ContentValues();
|
||||
int newFlagDlFull = 0;
|
||||
int newFlagDlPartial = 0;
|
||||
int newFlagDeleted = 0;
|
||||
if (oldFlags != null) {
|
||||
if (oldFlags.contains(Flag.X_DOWNLOADED_FULL.toString())) {
|
||||
newFlagDlFull = 1;
|
||||
}
|
||||
if (oldFlags.contains(Flag.X_DOWNLOADED_PARTIAL.toString())) {
|
||||
newFlagDlPartial = 1;
|
||||
}
|
||||
if (oldFlags.contains(Flag.DELETED.toString())) {
|
||||
newFlagDeleted = 1;
|
||||
}
|
||||
}
|
||||
// Always commit the new flags.
|
||||
// Note: We don't have to pay the cost of rewriting the old string,
|
||||
// because the old flag will be ignored, and will eventually be overwritten
|
||||
// anyway.
|
||||
values.put("flag_downloaded_full", newFlagDlFull);
|
||||
values.put("flag_downloaded_partial", newFlagDlPartial);
|
||||
values.put("flag_deleted", newFlagDeleted);
|
||||
int rowId = cursor.getInt(columnId);
|
||||
mDb.update("messages", values, "id=" + rowId, null);
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Folder getFolder(String name) throws MessagingException {
|
||||
|
@ -681,7 +750,8 @@ public class LocalStore extends Store {
|
|||
private final String POPULATE_MESSAGE_SELECT_COLUMNS =
|
||||
"subject, sender_list, date, uid, flags, id, to_list, cc_list, " +
|
||||
"bcc_list, reply_to_list, attachment_count, internal_date, message_id, " +
|
||||
"store_flag_1, store_flag_2";
|
||||
"store_flag_1, store_flag_2, flag_downloaded_full, flag_downloaded_partial, " +
|
||||
"flag_deleted";
|
||||
|
||||
/**
|
||||
* Populate a message from a cursor with the following columns:
|
||||
|
@ -701,6 +771,9 @@ public class LocalStore extends Store {
|
|||
* 12 message id (from Mime headers)
|
||||
* 13 store flag 1
|
||||
* 14 store flag 2
|
||||
* 15 flag "downloaded full"
|
||||
* 16 flag "downloaded partial"
|
||||
* 17 flag "deleted"
|
||||
*/
|
||||
private void populateMessageFromGetMessageCursor(LocalMessage message, Cursor cursor)
|
||||
throws MessagingException{
|
||||
|
@ -731,6 +804,9 @@ public class LocalStore extends Store {
|
|||
message.setMessageId(cursor.getString(12));
|
||||
message.setFlagInternal(Flag.X_STORE_1, (0 != cursor.getInt(13)));
|
||||
message.setFlagInternal(Flag.X_STORE_2, (0 != cursor.getInt(14)));
|
||||
message.setFlagInternal(Flag.X_DOWNLOADED_FULL, (0 != cursor.getInt(15)));
|
||||
message.setFlagInternal(Flag.X_DOWNLOADED_PARTIAL, (0 != cursor.getInt(16)));
|
||||
message.setFlagInternal(Flag.DELETED, (0 != cursor.getInt(17)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -833,6 +909,12 @@ public class LocalStore extends Store {
|
|||
sql.append("store_flag_1 = 1 AND ");
|
||||
} else if (flag == Flag.X_STORE_2) {
|
||||
sql.append("store_flag_2 = 1 AND ");
|
||||
} else if (flag == Flag.X_DOWNLOADED_FULL) {
|
||||
sql.append("flag_downloaded_full = 1 AND ");
|
||||
} else if (flag == Flag.X_DOWNLOADED_PARTIAL) {
|
||||
sql.append("flag_downloaded_partial = 1 AND ");
|
||||
} else if (flag == Flag.DELETED) {
|
||||
sql.append("flag_deleted = 1 AND ");
|
||||
} else {
|
||||
throw new MessagingException("Unsupported flag " + flag);
|
||||
}
|
||||
|
@ -844,6 +926,12 @@ public class LocalStore extends Store {
|
|||
sql.append("store_flag_1 = 0 AND ");
|
||||
} else if (flag == Flag.X_STORE_2) {
|
||||
sql.append("store_flag_2 = 0 AND ");
|
||||
} else if (flag == Flag.X_DOWNLOADED_FULL) {
|
||||
sql.append("flag_downloaded_full = 0 AND ");
|
||||
} else if (flag == Flag.X_DOWNLOADED_PARTIAL) {
|
||||
sql.append("flag_downloaded_partial = 0 AND ");
|
||||
} else if (flag == Flag.DELETED) {
|
||||
sql.append("flag_deleted = 0 AND ");
|
||||
} else {
|
||||
throw new MessagingException("Unsupported flag " + flag);
|
||||
}
|
||||
|
@ -968,6 +1056,11 @@ public class LocalStore extends Store {
|
|||
cv.put("message_id", ((MimeMessage)message).getMessageId());
|
||||
cv.put("store_flag_1", makeFlagNumeric(message, Flag.X_STORE_1));
|
||||
cv.put("store_flag_2", makeFlagNumeric(message, Flag.X_STORE_2));
|
||||
cv.put("flag_downloaded_full",
|
||||
makeFlagNumeric(message, Flag.X_DOWNLOADED_FULL));
|
||||
cv.put("flag_downloaded_partial",
|
||||
makeFlagNumeric(message, Flag.X_DOWNLOADED_PARTIAL));
|
||||
cv.put("flag_deleted", makeFlagNumeric(message, Flag.DELETED));
|
||||
long messageId = mDb.insert("messages", "uid", cv);
|
||||
for (Part attachment : attachments) {
|
||||
saveAttachment(messageId, attachment, copy);
|
||||
|
@ -1021,7 +1114,8 @@ public class LocalStore extends Store {
|
|||
+ "folder_id = ?, to_list = ?, cc_list = ?, bcc_list = ?, "
|
||||
+ "html_content = ?, text_content = ?, reply_to_list = ?, "
|
||||
+ "attachment_count = ?, message_id = ?, store_flag_1 = ?, "
|
||||
+ "store_flag_2 = ? "
|
||||
+ "store_flag_2 = ?, flag_downloaded_full = ?, "
|
||||
+ "flag_downloaded_partial = ?, flag_deleted = ? "
|
||||
+ "WHERE id = ?",
|
||||
new Object[] {
|
||||
message.getUid(),
|
||||
|
@ -1045,6 +1139,9 @@ public class LocalStore extends Store {
|
|||
message.getMessageId(),
|
||||
makeFlagNumeric(message, Flag.X_STORE_1),
|
||||
makeFlagNumeric(message, Flag.X_STORE_2),
|
||||
makeFlagNumeric(message, Flag.X_DOWNLOADED_FULL),
|
||||
makeFlagNumeric(message, Flag.X_DOWNLOADED_PARTIAL),
|
||||
makeFlagNumeric(message, Flag.DELETED),
|
||||
|
||||
message.mId
|
||||
});
|
||||
|
@ -1318,6 +1415,9 @@ public class LocalStore extends Store {
|
|||
* Transactionally combine a key/value and a complete message flags flip. Used
|
||||
* for setting sync bits in messages.
|
||||
*
|
||||
* Note: Not all flags are supported here and can only be changed with Message.setFlag().
|
||||
* For example, Flag.DELETED has side effects (removes attachments).
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param setFlags
|
||||
|
@ -1340,6 +1440,10 @@ public class LocalStore extends Store {
|
|||
cv.put("store_flag_1", 1);
|
||||
} else if (flag == Flag.X_STORE_2) {
|
||||
cv.put("store_flag_2", 1);
|
||||
} else if (flag == Flag.X_DOWNLOADED_FULL) {
|
||||
cv.put("flag_downloaded_full", 1);
|
||||
} else if (flag == Flag.X_DOWNLOADED_PARTIAL) {
|
||||
cv.put("flag_downloaded_partial", 1);
|
||||
} else {
|
||||
throw new MessagingException("Unsupported flag " + flag);
|
||||
}
|
||||
|
@ -1351,6 +1455,10 @@ public class LocalStore extends Store {
|
|||
cv.put("store_flag_1", 0);
|
||||
} else if (flag == Flag.X_STORE_2) {
|
||||
cv.put("store_flag_2", 0);
|
||||
} else if (flag == Flag.X_DOWNLOADED_FULL) {
|
||||
cv.put("flag_downloaded_full", 0);
|
||||
} else if (flag == Flag.X_DOWNLOADED_PARTIAL) {
|
||||
cv.put("flag_downloaded_partial", 0);
|
||||
} else {
|
||||
throw new MessagingException("Unsupported flag " + flag);
|
||||
}
|
||||
|
@ -1460,12 +1568,16 @@ public class LocalStore extends Store {
|
|||
* Set the flags on the message.
|
||||
*/
|
||||
mDb.execSQL("UPDATE messages "
|
||||
+ "SET flags = ?, store_flag_1 = ?, store_flag_2 = ? "
|
||||
+ "SET flags = ?, store_flag_1 = ?, store_flag_2 = ?, "
|
||||
+ "flag_downloaded_full = ?, flag_downloaded_partial = ?, flag_deleted = ? "
|
||||
+ "WHERE id = ?",
|
||||
new Object[] {
|
||||
makeFlagsString(this),
|
||||
makeFlagNumeric(this, Flag.X_STORE_1),
|
||||
makeFlagNumeric(this, Flag.X_STORE_2),
|
||||
makeFlagNumeric(this, Flag.X_DOWNLOADED_FULL),
|
||||
makeFlagNumeric(this, Flag.X_DOWNLOADED_PARTIAL),
|
||||
makeFlagNumeric(this, Flag.DELETED),
|
||||
mId
|
||||
});
|
||||
}
|
||||
|
@ -1481,7 +1593,10 @@ public class LocalStore extends Store {
|
|||
StringBuilder sb = null;
|
||||
boolean nonEmpty = false;
|
||||
for (Flag flag : Flag.values()) {
|
||||
if ((flag != Flag.X_STORE_1 && flag != Flag.X_STORE_2) && message.isSet(flag)) {
|
||||
if (flag != Flag.X_STORE_1 && flag != Flag.X_STORE_2 &&
|
||||
flag != Flag.X_DOWNLOADED_FULL && flag != Flag.X_DOWNLOADED_PARTIAL &&
|
||||
flag != Flag.DELETED &&
|
||||
message.isSet(flag)) {
|
||||
if (sb == null) {
|
||||
sb = new StringBuilder();
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ public class LocalStoreUnitTests extends AndroidTestCase {
|
|||
private static final String MESSAGE_ID = "Test-Message-ID";
|
||||
private static final String MESSAGE_ID_2 = "Test-Message-ID-Second";
|
||||
|
||||
private static final int DATABASE_VERSION = 22;
|
||||
private static final int DATABASE_VERSION = 23;
|
||||
|
||||
/* These values are provided by setUp() */
|
||||
private String mLocalStoreUri = null;
|
||||
|
@ -409,6 +409,69 @@ public class LocalStoreUnitTests extends AndroidTestCase {
|
|||
assertTrue(retrievedEntry.isSet(Flag.X_STORE_2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that messages are being stored with download & delete state flags properly persisted.
|
||||
*
|
||||
* This variant tests appendMessages() and updateMessages() and getMessage()
|
||||
*/
|
||||
public void testDownloadAndDeletedFlags() throws MessagingException {
|
||||
final MimeMessage message = buildTestMessage(RECIPIENT_TO, SENDER, SUBJECT, BODY);
|
||||
message.setMessageId(MESSAGE_ID);
|
||||
message.setFlag(Flag.X_STORE_1, true);
|
||||
message.setFlag(Flag.X_STORE_2, false);
|
||||
message.setFlag(Flag.X_DOWNLOADED_FULL, true);
|
||||
message.setFlag(Flag.X_DOWNLOADED_PARTIAL, false);
|
||||
message.setFlag(Flag.DELETED, false);
|
||||
|
||||
mFolder.open(OpenMode.READ_WRITE, null);
|
||||
mFolder.appendMessages(new Message[]{ message });
|
||||
String localUid = message.getUid();
|
||||
|
||||
// Now try to read it back from the database using getMessage()
|
||||
|
||||
MimeMessage retrieved = (MimeMessage) mFolder.getMessage(localUid);
|
||||
assertEquals(MESSAGE_ID, retrieved.getMessageId());
|
||||
assertTrue(retrieved.isSet(Flag.X_STORE_1));
|
||||
assertFalse(retrieved.isSet(Flag.X_STORE_2));
|
||||
assertTrue(retrieved.isSet(Flag.X_DOWNLOADED_FULL));
|
||||
assertFalse(retrieved.isSet(Flag.X_DOWNLOADED_PARTIAL));
|
||||
assertFalse(retrieved.isSet(Flag.DELETED));
|
||||
|
||||
// Now try to update it using updateMessages()
|
||||
|
||||
retrieved.setFlag(Flag.X_STORE_1, false);
|
||||
retrieved.setFlag(Flag.X_STORE_2, true);
|
||||
retrieved.setFlag(Flag.X_DOWNLOADED_FULL, false);
|
||||
retrieved.setFlag(Flag.X_DOWNLOADED_PARTIAL, true);
|
||||
mFolder.updateMessage((LocalStore.LocalMessage)retrieved);
|
||||
|
||||
// And read back once more to confirm the change (using getMessages() to confirm "just one")
|
||||
Message[] retrievedArray = mFolder.getMessages(null);
|
||||
assertEquals(1, retrievedArray.length);
|
||||
MimeMessage retrievedEntry = (MimeMessage) retrievedArray[0];
|
||||
assertEquals(MESSAGE_ID, retrievedEntry.getMessageId());
|
||||
|
||||
assertFalse(retrievedEntry.isSet(Flag.X_STORE_1));
|
||||
assertTrue(retrievedEntry.isSet(Flag.X_STORE_2));
|
||||
assertFalse(retrievedEntry.isSet(Flag.X_DOWNLOADED_FULL));
|
||||
assertTrue(retrievedEntry.isSet(Flag.X_DOWNLOADED_PARTIAL));
|
||||
assertFalse(retrievedEntry.isSet(Flag.DELETED));
|
||||
|
||||
// Finally test setFlag(Flag.DELETED)
|
||||
retrievedEntry.setFlag(Flag.DELETED, true);
|
||||
mFolder.updateMessage((LocalStore.LocalMessage)retrievedEntry);
|
||||
Message[] retrievedArray2 = mFolder.getMessages(null);
|
||||
assertEquals(1, retrievedArray2.length);
|
||||
MimeMessage retrievedEntry2 = (MimeMessage) retrievedArray2[0];
|
||||
assertEquals(MESSAGE_ID, retrievedEntry2.getMessageId());
|
||||
|
||||
assertFalse(retrievedEntry2.isSet(Flag.X_STORE_1));
|
||||
assertTrue(retrievedEntry2.isSet(Flag.X_STORE_2));
|
||||
assertFalse(retrievedEntry2.isSet(Flag.X_DOWNLOADED_FULL));
|
||||
assertTrue(retrievedEntry2.isSet(Flag.X_DOWNLOADED_PARTIAL));
|
||||
assertTrue(retrievedEntry2.isSet(Flag.DELETED));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that store flags are separated into separate columns and not replicated in the
|
||||
* (should be deprecated) string flags column.
|
||||
|
@ -420,6 +483,9 @@ public class LocalStoreUnitTests extends AndroidTestCase {
|
|||
message.setFlag(Flag.FLAGGED, true);
|
||||
message.setFlag(Flag.X_STORE_1, true);
|
||||
message.setFlag(Flag.X_STORE_2, true);
|
||||
message.setFlag(Flag.X_DOWNLOADED_FULL, true);
|
||||
message.setFlag(Flag.X_DOWNLOADED_PARTIAL, true);
|
||||
message.setFlag(Flag.DELETED, true);
|
||||
|
||||
mFolder.open(OpenMode.READ_WRITE, null);
|
||||
mFolder.appendMessages(new Message[]{ message });
|
||||
|
@ -435,27 +501,31 @@ public class LocalStoreUnitTests extends AndroidTestCase {
|
|||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = db.rawQuery(
|
||||
"SELECT flags, store_flag_1, store_flag_2" +
|
||||
"SELECT flags, store_flag_1, store_flag_2," +
|
||||
" flag_downloaded_full, flag_downloaded_partial, flag_deleted" +
|
||||
" FROM messages" +
|
||||
" WHERE uid = ? AND folder_id = ?",
|
||||
new String[] {
|
||||
localUid, Long.toString(folderId)
|
||||
});
|
||||
if (!cursor.moveToNext()) {
|
||||
fail("appended message not found");
|
||||
}
|
||||
assertTrue("appended message not found", cursor.moveToNext());
|
||||
String flagString = cursor.getString(0);
|
||||
String[] flags = flagString.split(",");
|
||||
assertEquals(2, flags.length); // 2 = SEEN & FLAGGED
|
||||
for (String flag : flags) {
|
||||
assertFalse("storeFlag1 in string", flag.equals(Flag.X_STORE_1.toString()));
|
||||
assertFalse("storeFlag2 in string", flag.equals(Flag.X_STORE_2.toString()));
|
||||
assertFalse("flag_downloaded_full in string",
|
||||
flag.equals(Flag.X_DOWNLOADED_FULL.toString()));
|
||||
assertFalse("flag_downloaded_partial in string",
|
||||
flag.equals(Flag.X_DOWNLOADED_PARTIAL.toString()));
|
||||
assertFalse("flag_deleted in string", flag.equals(Flag.DELETED.toString()));
|
||||
}
|
||||
|
||||
int flag1 = cursor.getInt(1); // store flag 1 is set
|
||||
assertEquals(1, flag1);
|
||||
int flag2 = cursor.getInt(2); // store flag 2 is set
|
||||
assertEquals(1, flag2);
|
||||
assertEquals(1, cursor.getInt(1)); // store flag 1 is set
|
||||
assertEquals(1, cursor.getInt(2)); // store flag 2 is set
|
||||
assertEquals(1, cursor.getInt(3)); // flag_downloaded_full is set
|
||||
assertEquals(1, cursor.getInt(4)); // flag_downloaded_partial is set
|
||||
assertEquals(1, cursor.getInt(5)); // flag_deleted is set
|
||||
}
|
||||
finally {
|
||||
if (cursor != null) {
|
||||
|
@ -485,7 +555,17 @@ public class LocalStoreUnitTests extends AndroidTestCase {
|
|||
message4.setFlag(Flag.X_STORE_1, true);
|
||||
message4.setFlag(Flag.X_STORE_2, true);
|
||||
|
||||
Message[] allOriginals = new Message[]{ message1, message2, message3, message4 };
|
||||
final MimeMessage message5 = buildTestMessage(RECIPIENT_TO, SENDER, SUBJECT, BODY);
|
||||
message5.setFlag(Flag.X_DOWNLOADED_FULL, true);
|
||||
|
||||
final MimeMessage message6 = buildTestMessage(RECIPIENT_TO, SENDER, SUBJECT, BODY);
|
||||
message6.setFlag(Flag.X_DOWNLOADED_PARTIAL, true);
|
||||
|
||||
final MimeMessage message7 = buildTestMessage(RECIPIENT_TO, SENDER, SUBJECT, BODY);
|
||||
message7.setFlag(Flag.DELETED, true);
|
||||
|
||||
Message[] allOriginals = new Message[] {
|
||||
message1, message2, message3, message4, message5, message6, message7 };
|
||||
|
||||
mFolder.open(OpenMode.READ_WRITE, null);
|
||||
mFolder.appendMessages(allOriginals);
|
||||
|
@ -506,13 +586,25 @@ public class LocalStoreUnitTests extends AndroidTestCase {
|
|||
checkGottenMessages("store_1 set", new Message[]{ message2, message4 }, getSome1);
|
||||
|
||||
Message[] getSome2 = mFolder.getMessages(null, new Flag[]{ Flag.X_STORE_1 }, null);
|
||||
checkGottenMessages("store_1 clear", new Message[]{ message1, message3 }, getSome2);
|
||||
checkGottenMessages("store_1 clear",
|
||||
new Message[]{ message1, message3, message5, message6, message7 }, getSome2);
|
||||
|
||||
Message[] getSome3 = mFolder.getMessages(new Flag[]{ Flag.X_STORE_2 }, null, null);
|
||||
checkGottenMessages("store_2 set", new Message[]{ message3, message4 }, getSome3);
|
||||
|
||||
Message[] getSome4 = mFolder.getMessages(null, new Flag[]{ Flag.X_STORE_2 }, null);
|
||||
checkGottenMessages("store_2 clear", new Message[]{ message1, message2 }, getSome4);
|
||||
checkGottenMessages("store_2 clear",
|
||||
new Message[]{ message1, message2, message5, message6, message7 }, getSome4);
|
||||
|
||||
Message[] getOne1 = mFolder.getMessages(new Flag[]{ Flag.X_DOWNLOADED_FULL }, null, null);
|
||||
checkGottenMessages("downloaded full", new Message[]{ message5 }, getOne1);
|
||||
|
||||
Message[] getOne2 = mFolder.getMessages(new Flag[]{ Flag.X_DOWNLOADED_PARTIAL }, null,
|
||||
null);
|
||||
checkGottenMessages("downloaded partial", new Message[]{ message6 }, getOne2);
|
||||
|
||||
Message[] getOne3 = mFolder.getMessages(new Flag[]{ Flag.DELETED }, null, null);
|
||||
checkGottenMessages("deleted", new Message[]{ message7 }, getOne3);
|
||||
|
||||
// Multi-flag selections
|
||||
Message[] getSingle1 = mFolder.getMessages(new Flag[]{ Flag.X_STORE_1, Flag.X_STORE_2 },
|
||||
|
@ -521,7 +613,8 @@ public class LocalStoreUnitTests extends AndroidTestCase {
|
|||
|
||||
Message[] getSingle2 = mFolder.getMessages(null,
|
||||
new Flag[]{ Flag.X_STORE_1, Flag.X_STORE_2 }, null);
|
||||
checkGottenMessages("both clear", new Message[]{ message1 }, getSingle2);
|
||||
checkGottenMessages("both clear", new Message[]{ message1, message5, message6, message7 },
|
||||
getSingle2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -853,6 +946,76 @@ public class LocalStoreUnitTests extends AndroidTestCase {
|
|||
checkAllTablesFound(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check upgrade from db version 22 to latest.
|
||||
* Flags must be migrated to new columns.
|
||||
*/
|
||||
public void testDbUpgrade22ToLatest() throws MessagingException, URISyntaxException {
|
||||
final URI uri = new URI(mLocalStoreUri);
|
||||
final String dbPath = uri.getPath();
|
||||
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbPath, null);
|
||||
|
||||
// create sample version 22 db tables
|
||||
createSampleDb(db, 22);
|
||||
|
||||
// insert three messages, one for each migration flag
|
||||
final ContentValues inMessage1 = new ContentValues();
|
||||
inMessage1.put("message_id", (String) "x"); // message_id text == String
|
||||
inMessage1.put("flags", Flag.X_DOWNLOADED_FULL.toString());
|
||||
final ContentValues outMessage1 = new ContentValues(inMessage1);
|
||||
outMessage1.put("id", db.insert("messages", null, inMessage1));
|
||||
|
||||
final ContentValues inMessage2 = new ContentValues();
|
||||
inMessage2.put("message_id", (String) "y"); // message_id text == String
|
||||
inMessage2.put("flags", Flag.X_DOWNLOADED_PARTIAL.toString());
|
||||
final ContentValues outMessage2 = new ContentValues(inMessage2);
|
||||
outMessage2.put("id", db.insert("messages", null, inMessage2));
|
||||
|
||||
final ContentValues inMessage3 = new ContentValues();
|
||||
inMessage3.put("message_id", (String) "z"); // message_id text == String
|
||||
inMessage3.put("flags", Flag.DELETED.toString());
|
||||
final ContentValues outMessage3 = new ContentValues(inMessage3);
|
||||
outMessage3.put("id", db.insert("messages", null, inMessage3));
|
||||
|
||||
db.close();
|
||||
|
||||
// upgrade database 22 to latest
|
||||
LocalStore.newInstance(mLocalStoreUri, getContext(), null);
|
||||
|
||||
// database should be upgraded
|
||||
db = SQLiteDatabase.openOrCreateDatabase(dbPath, null);
|
||||
assertEquals("database should be upgraded", DATABASE_VERSION, db.getVersion());
|
||||
|
||||
// check for all "latest version" tables
|
||||
checkAllTablesFound(db);
|
||||
|
||||
// check message table for migrated flags
|
||||
String[] columns = new String[] { "id", "message_id", "flags",
|
||||
"flag_downloaded_full", "flag_downloaded_partial", "flag_deleted" };
|
||||
Cursor c = db.query("messages", columns, null, null, null, null, null);
|
||||
|
||||
for (int msgNum = 0; msgNum <= 2; ++msgNum) {
|
||||
assertTrue(c.moveToNext());
|
||||
ContentValues actualMessage = cursorToContentValues(c,
|
||||
new String[] { "primary", "text", "text", "integer", "integer", "integer" });
|
||||
String messageId = actualMessage.getAsString("message_id");
|
||||
int outDlFull = actualMessage.getAsInteger("flag_downloaded_full");
|
||||
int outDlPartial = actualMessage.getAsInteger("flag_downloaded_partial");
|
||||
int outDeleted = actualMessage.getAsInteger("flag_deleted");
|
||||
if ("x".equals(messageId)) {
|
||||
assertTrue("converted flag_downloaded_full",
|
||||
outDlFull == 1 && outDlPartial == 0 && outDeleted == 0);
|
||||
} else if ("y".equals(messageId)) {
|
||||
assertTrue("converted flag_downloaded_partial",
|
||||
outDlFull == 0 && outDlPartial == 1 && outDeleted == 0);
|
||||
} else if ("z".equals(messageId)) {
|
||||
assertTrue("converted flag_deleted",
|
||||
outDlFull == 0 && outDlPartial == 0 && outDeleted == 1);
|
||||
}
|
||||
}
|
||||
c.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the database to confirm that all tables, with all expected columns are found.
|
||||
*/
|
||||
|
@ -870,7 +1033,8 @@ public class LocalStoreUnitTests extends AndroidTestCase {
|
|||
new String[]{ "id", "folder_id", "uid", "subject", "date", "flags", "sender_list",
|
||||
"to_list", "cc_list", "bcc_list", "reply_to_list",
|
||||
"html_content", "text_content", "attachment_count",
|
||||
"internal_date", "store_flag_1", "store_flag_2" }
|
||||
"internal_date", "store_flag_1", "store_flag_2", "flag_downloaded_full",
|
||||
"flag_downloaded_partial", "flag_deleted" }
|
||||
));
|
||||
assertTrue("messages", foundNames.containsAll(expectedNames));
|
||||
|
||||
|
@ -906,6 +1070,9 @@ public class LocalStoreUnitTests extends AndroidTestCase {
|
|||
"internal_date INTEGER" +
|
||||
((version >= 19) ? ", message_id TEXT" : "") +
|
||||
((version >= 22) ? ", store_flag_1 INTEGER, store_flag_2 INTEGER" : "") +
|
||||
((version >= 23) ?
|
||||
", flag_downloaded_full INTEGER, flag_downloaded_partial INTEGER" : "") +
|
||||
((version >= 23) ? ", flag_deleted INTEGER" : "") +
|
||||
")");
|
||||
db.execSQL("DROP TABLE IF EXISTS attachments");
|
||||
db.execSQL("CREATE TABLE attachments (id INTEGER PRIMARY KEY, message_id INTEGER," +
|
||||
|
|
Loading…
Reference in New Issue