Fix SQL for DELETE_ORPHAN_BODIES and DELETE_BODY.

and add unit tests.
This commit is contained in:
Mihai Preda 2009-08-03 15:05:50 +02:00
parent 5c3f1f8cb7
commit fb7974f5bf
2 changed files with 113 additions and 32 deletions

View File

@ -148,12 +148,12 @@ public class EmailProvider extends ContentProvider {
EmailContent.RECORD_ID + '=';
private static final String DELETE_ORPHAN_BODIES = "delete from " + Body.TABLE_NAME +
" where " + EmailContent.RECORD_ID + " in " + "(select " + EmailContent.RECORD_ID +
" where " + BodyColumns.MESSAGE_KEY + " in " + "(select " + BodyColumns.MESSAGE_KEY +
" from " + Body.TABLE_NAME + " except select " + EmailContent.RECORD_ID + " from " +
Message.TABLE_NAME + ')';
private static final String DELETE_BODY = "delete from " + Body.TABLE_NAME +
" where " + EmailContent.RECORD_ID + '=';
" where " + BodyColumns.MESSAGE_KEY + '=';
static {
// Email URI matching table
@ -575,7 +575,7 @@ public class EmailProvider extends ContentProvider {
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int match = sURIMatcher.match(uri);
final int match = sURIMatcher.match(uri);
Context context = getContext();
// Pick the correct database for this operation
// If we're in a transaction already (which would happen during applyBatch), then the
@ -586,7 +586,6 @@ public class EmailProvider extends ContentProvider {
int table = match >> BASE_SHIFT;
String id = "0";
boolean messageDeletion = false;
boolean deleteOrphanedBodies = false;
if (Email.LOGD) {
Log.v(TAG, "EmailProvider.delete: uri=" + uri + ", match is " + match);
@ -623,9 +622,6 @@ public class EmailProvider extends ContentProvider {
db.execSQL("attach \"" + bodyFileName + "\" as BodyDatabase");
db.beginTransaction();
}
if (match != MESSAGE_ID) {
deleteOrphanedBodies = true;
}
break;
}
switch (match) {
@ -663,12 +659,12 @@ public class EmailProvider extends ContentProvider {
throw new IllegalArgumentException("Unknown URI " + uri);
}
if (messageDeletion) {
if (deleteOrphanedBodies) {
// Delete any orphaned Body records
db.execSQL(DELETE_ORPHAN_BODIES);
} else {
if (match == MESSAGE_ID) {
// Delete the Body record associated with the deleted message
db.execSQL(DELETE_BODY + id);
} else {
// Delete any orphaned Body records
db.execSQL(DELETE_ORPHAN_BODIES);
}
if (!mInTransaction) {
db.setTransactionSuccessful();

View File

@ -130,6 +130,26 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
// The lengths need to be kept in ascending order
private static long[] expectedAttachmentSizes = new long[] {31415L, 97701L, 151213L};
/*
* Returns null if the message has no body.
*/
private Body loadBodyForMessageId(long messageId) {
Cursor c = null;
try {
c = mMockContext.getContentResolver().query(
EmailContent.Body.CONTENT_URI,
EmailContent.Body.CONTENT_PROJECTION,
EmailContent.Body.MESSAGE_KEY + "=?",
new String[] {String.valueOf(messageId)},
null);
int numBodies = c.getCount();
assertTrue("at most one body", numBodies < 2);
return c.moveToFirst() ? EmailContent.getContent(c, Body.class) : null;
} finally {
c.close();
}
}
/**
* Test simple message save/retrieve
*
@ -161,26 +181,9 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
ProviderTestUtils.assertMessageEqual("testMessageSave", message2, message2get);
// Now see if there's a body saved with the right stuff
// TODO it might make sense to add a function to restore the body with the message id
Cursor c = null;
try {
c = mMockContext.getContentResolver().query(
EmailContent.Body.CONTENT_URI,
EmailContent.Body.CONTENT_PROJECTION,
EmailContent.Body.MESSAGE_KEY + "=?",
new String[] {
String.valueOf(message2Id)
},
null);
int numBodies = c.getCount();
assertEquals(1, numBodies);
c.moveToFirst();
Body body2 = EmailContent.getContent(c, Body.class);
assertEquals("body text", text2, body2.mTextContent);
assertEquals("body html", html2, body2.mHtmlContent);
} finally {
c.close();
}
Body body2 = loadBodyForMessageId(message2Id);
assertEquals("body text", text2, body2.mTextContent);
assertEquals("body html", html2, body2.mHtmlContent);
// Message with attachments and body
Message message3 = ProviderTestUtils.setupMessage("message3", account1Id, box1Id, true,
@ -196,7 +199,7 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
long message3Id = message3.mId;
// Now check the attachments; there should be three and they should match name and size
c = null;
Cursor c = null;
try {
// Note that there is NO guarantee of the order of returned records in the general case,
// so we specifically ask for ordering by size. The expectedAttachmentSizes array must
@ -305,6 +308,88 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
assertEquals(0, numBoxes);
}
/**
* Test delete body.
* 1. create message without body (message id 1)
* 2. create message with body (message id 2. The body has _id 1 and messageKey 2).
* 3. delete first message.
* 4. verify that body for message 2 has not been deleted.
* 5. delete message 2, verify body is deleted.
*/
public void testDeleteBody() {
final ContentResolver resolver = mMockContext.getContentResolver();
// Create account and mailboxes
Account account1 = ProviderTestUtils.setupAccount("orphaned body", true, mMockContext);
long account1Id = account1.mId;
Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext);
long box1Id = box1.mId;
// 1. create message without body
Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false,
true, mMockContext);
long message1Id = message1.mId;
// 2. create message with body
Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true,
true, mMockContext);
long message2Id = message2.mId;
// verify body is there
assertNotNull(loadBodyForMessageId(message2Id));
// 3. delete first message
resolver.delete(ContentUris.withAppendedId(Message.CONTENT_URI, message1Id), null, null);
// 4. verify body for second message wasn't deleted
assertNotNull(loadBodyForMessageId(message2Id));
// 5. delete second message, check its body is deleted
resolver.delete(ContentUris.withAppendedId(Message.CONTENT_URI, message2Id), null, null);
assertNull(loadBodyForMessageId(message2Id));
}
/**
* Test delete orphan bodies.
* 1. create message without body (message id 1)
* 2. create message with body (message id 2. Body has _id 1 and messageKey 2).
* 3. delete first message.
* 4. delete some other mailbox -- this triggers delete orphan bodies.
* 5. verify that body for message 2 has not been deleted.
*/
public void testDeleteOrphanBodies() {
final ContentResolver resolver = mMockContext.getContentResolver();
// Create account and twa mailboxes
Account account1 = ProviderTestUtils.setupAccount("orphaned body", true, mMockContext);
long account1Id = account1.mId;
Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext);
long box1Id = box1.mId;
Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account1Id, true, mMockContext);
long box2Id = box2.mId;
// 1. create message without body
Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false,
true, mMockContext);
long message1Id = message1.mId;
// 2. create message with body
Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true,
true, mMockContext);
long message2Id = message2.mId;
//verify body is there
Body body = loadBodyForMessageId(message2Id);
assertNotNull(loadBodyForMessageId(message2Id));
// 3. delete first message
resolver.delete(ContentUris.withAppendedId(Message.CONTENT_URI, message1Id), null, null);
// 4. delete some mailbox (because it triggers "delete orphan bodies")
resolver.delete(ContentUris.withAppendedId(Mailbox.CONTENT_URI, box2Id), null, null);
// 5. verify body for second message wasn't deleted during "delete orphan bodies"
assertNotNull(loadBodyForMessageId(message2Id));
}
/**
* Test delete mailbox
*/