Merge "Add the messageCount column to the mailbox table."

This commit is contained in:
Makoto Onuki 2010-08-02 16:01:32 -07:00 committed by Android (Google) Code Review
commit d0c2178063
3 changed files with 181 additions and 5 deletions

View File

@ -76,7 +76,7 @@ public abstract class EmailContent {
};
public static final int ID_PROJECTION_COLUMN = 0;
private static final String ID_SELECTION = RECORD_ID + " =?";
public static final String ID_SELECTION = RECORD_ID + " =?";
public static final String FIELD_COLUMN_NAME = "field";
public static final String ADD_COLUMN_NAME = "add";
@ -1944,6 +1944,8 @@ public abstract class EmailContent {
public static final String VISIBLE_LIMIT = "visibleLimit";
// Sync status (can be used as desired by sync services)
public static final String SYNC_STATUS = "syncStatus";
// Number of messages in the mailbox.
public static final String MESSAGE_COUNT = "messageCount";
}
public static final class Mailbox extends EmailContent implements SyncColumns, MailboxColumns {
@ -1967,6 +1969,7 @@ public abstract class EmailContent {
public int mFlags;
public int mVisibleLimit;
public String mSyncStatus;
public int mMessageCount;
public static final int CONTENT_ID_COLUMN = 0;
public static final int CONTENT_DISPLAY_NAME_COLUMN = 1;
@ -1984,13 +1987,14 @@ public abstract class EmailContent {
public static final int CONTENT_FLAGS_COLUMN = 13;
public static final int CONTENT_VISIBLE_LIMIT_COLUMN = 14;
public static final int CONTENT_SYNC_STATUS_COLUMN = 15;
public static final int CONTENT_MESSAGE_COUNT_COLUMN = 16;
public static final String[] CONTENT_PROJECTION = new String[] {
RECORD_ID, MailboxColumns.DISPLAY_NAME, MailboxColumns.SERVER_ID,
MailboxColumns.PARENT_SERVER_ID, MailboxColumns.ACCOUNT_KEY, MailboxColumns.TYPE,
MailboxColumns.DELIMITER, MailboxColumns.SYNC_KEY, MailboxColumns.SYNC_LOOKBACK,
MailboxColumns.SYNC_INTERVAL, MailboxColumns.SYNC_TIME,MailboxColumns.UNREAD_COUNT,
MailboxColumns.FLAG_VISIBLE, MailboxColumns.FLAGS, MailboxColumns.VISIBLE_LIMIT,
MailboxColumns.SYNC_STATUS
MailboxColumns.SYNC_STATUS, MailboxColumns.MESSAGE_COUNT
};
public static final long NO_MAILBOX = -1;
@ -2099,6 +2103,7 @@ public abstract class EmailContent {
mFlags = cursor.getInt(CONTENT_FLAGS_COLUMN);
mVisibleLimit = cursor.getInt(CONTENT_VISIBLE_LIMIT_COLUMN);
mSyncStatus = cursor.getString(CONTENT_SYNC_STATUS_COLUMN);
mMessageCount = cursor.getInt(CONTENT_MESSAGE_COUNT_COLUMN);
return this;
}
@ -2120,6 +2125,7 @@ public abstract class EmailContent {
values.put(MailboxColumns.FLAGS, mFlags);
values.put(MailboxColumns.VISIBLE_LIMIT, mVisibleLimit);
values.put(MailboxColumns.SYNC_STATUS, mSyncStatus);
values.put(MailboxColumns.MESSAGE_COUNT, mMessageCount);
return values;
}

View File

@ -81,7 +81,8 @@ public class EmailProvider extends ContentProvider {
// Version 10: Add meeting info to message table
// Version 11: Add content and flags to attachment table
// Version 12: Add content_bytes to attachment table. content is deprecated.
public static final int DATABASE_VERSION = 12;
// Version 13: Add messageCount to Mailbox table.
public static final int DATABASE_VERSION = 13;
// Any changes to the database format *must* include update-in-place code.
// Original version: 2
@ -350,6 +351,9 @@ public class EmailProvider extends ContentProvider {
// Add triggers to keep unread count accurate per mailbox
// NOTE: SQLite's before triggers are not safe when recursive triggers are involved.
// Use caution when changing them.
// Insert a message; if flagRead is zero, add to the unread count of the message's mailbox
db.execSQL("create trigger unread_message_insert before insert on " + Message.TABLE_NAME +
" when NEW." + MessageColumns.FLAG_READ + "=0" +
@ -387,7 +391,36 @@ public class EmailProvider extends ContentProvider {
" when 0 then -1 else 1 end" +
" where " + EmailContent.RECORD_ID + "=OLD." + MessageColumns.MAILBOX_KEY +
"; end");
}
// Add triggers to update message count per mailbox
// Insert a message.
db.execSQL("create trigger message_count_message_insert after insert on " +
Message.TABLE_NAME +
" begin update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.MESSAGE_COUNT +
'=' + MailboxColumns.MESSAGE_COUNT + "+1" +
" where " + EmailContent.RECORD_ID + "=NEW." + MessageColumns.MAILBOX_KEY +
"; end");
// Delete a message; if flagRead is zero, decrement the unread count of the msg's mailbox
db.execSQL("create trigger message_count_message_delete after delete on " +
Message.TABLE_NAME +
" begin update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.MESSAGE_COUNT +
'=' + MailboxColumns.MESSAGE_COUNT + "-1" +
" where " + EmailContent.RECORD_ID + "=OLD." + MessageColumns.MAILBOX_KEY +
"; end");
// Change a message's mailbox
db.execSQL("create trigger message_count_message_move after update of " +
MessageColumns.MAILBOX_KEY + " on " + Message.TABLE_NAME +
" begin update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.MESSAGE_COUNT +
'=' + MailboxColumns.MESSAGE_COUNT + "-1" +
" where " + EmailContent.RECORD_ID + "=OLD." + MessageColumns.MAILBOX_KEY +
"; update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.MESSAGE_COUNT +
'=' + MailboxColumns.MESSAGE_COUNT + "+1" +
" where " + EmailContent.RECORD_ID + "=NEW." + MessageColumns.MAILBOX_KEY +
"; end");
}
static void resetMessageTable(SQLiteDatabase db, int oldVersion, int newVersion) {
try {
@ -477,7 +510,8 @@ public class EmailProvider extends ContentProvider {
+ MailboxColumns.FLAG_VISIBLE + " integer, "
+ MailboxColumns.FLAGS + " integer, "
+ MailboxColumns.VISIBLE_LIMIT + " integer, "
+ MailboxColumns.SYNC_STATUS + " text"
+ MailboxColumns.SYNC_STATUS + " text, "
+ MailboxColumns.MESSAGE_COUNT + " integer not null default 0"
+ ");";
db.execSQL("create table " + Mailbox.TABLE_NAME + s);
db.execSQL("create index mailbox_" + MailboxColumns.SERVER_ID
@ -782,6 +816,18 @@ public class EmailProvider extends ContentProvider {
}
oldVersion = 12;
}
if (oldVersion == 12) {
try {
db.execSQL("alter table " + Mailbox.TABLE_NAME
+ " add column " + Mailbox.MESSAGE_COUNT
+" integer not null default 0" + ";");
recalculateMessageCount(db);
} catch (SQLException e) {
// Shouldn't be needed unless we're debugging and interrupt the process
Log.w(TAG, "Exception upgrading EmailProvider.db from 12 to 13 " + e);
}
oldVersion = 13;
}
}
@Override
@ -1252,4 +1298,14 @@ public class EmailProvider extends ContentProvider {
db.endTransaction();
}
}
/**
* Count the number of messages in each mailbox, and update the message count column.
*/
/* package */ static void recalculateMessageCount(SQLiteDatabase db) {
db.execSQL("update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.MESSAGE_COUNT +
"= (select count(*) from " + Message.TABLE_NAME +
" where " + Message.MAILBOX_KEY + " = " +
Mailbox.TABLE_NAME + "." + EmailContent.RECORD_ID + ")");
}
}

View File

@ -33,6 +33,7 @@ import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
@ -1805,4 +1806,117 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
Account a2a = Account.restoreAccountWithId(mMockContext, a2.mId);
assertEquals(Account.FLAGS_VIBRATE_ALWAYS, a2a.mFlags);
}
/**
* @return the number of messages in a mailbox.
*/
private int getMessageCount(long mailboxId) {
Mailbox b = Mailbox.restoreMailboxWithId(mMockContext, mailboxId);
return b.mMessageCount;
}
/** Set -1 to the message count of all mailboxes for the recalculateMessageCount test. */
private void setMinusOneToMessageCounts() {
ContentValues values = new ContentValues();
values.put(MailboxColumns.MESSAGE_COUNT, -1);
getProvider().update(Mailbox.CONTENT_URI, values, null, null);
}
/**
* Test for the message count trrigers (insert/delete/move mailbox), and also
* {@link EmailProvider#recalculateMessageCount}.
*/
public void testMessageCount() {
final Context c = mMockContext;
// Create 2 accounts
Account a1 = ProviderTestUtils.setupAccount("holdflag-1", true, c);
Account a2 = ProviderTestUtils.setupAccount("holdflag-2", true, c);
// Create 2 mailboxes for each account
Mailbox b1 = ProviderTestUtils.setupMailbox("box1", a1.mId, true, c);
Mailbox b2 = ProviderTestUtils.setupMailbox("box2", a1.mId, true, c);
Mailbox b3 = ProviderTestUtils.setupMailbox("box3", a2.mId, true, c);
Mailbox b4 = ProviderTestUtils.setupMailbox("box4", a2.mId, true, c);
// 0. Check the initial values, just in case.
assertEquals(0, getMessageCount(b1.mId));
assertEquals(0, getMessageCount(b2.mId));
assertEquals(0, getMessageCount(b3.mId));
assertEquals(0, getMessageCount(b4.mId));
// 1. Test for insert triggers.
// Create some messages
Mailbox b = b1; // 1 message
Message m11 = ProviderTestUtils.setupMessage("1", b.mAccountKey, b.mId, true, true, c);
b = b2; // 2 messages
Message m21 = ProviderTestUtils.setupMessage("1", b.mAccountKey, b.mId, true, true, c);
Message m22 = ProviderTestUtils.setupMessage("1", b.mAccountKey, b.mId, true, true, c);
b = b3; // 3 messages
Message m31 = ProviderTestUtils.setupMessage("1", b.mAccountKey, b.mId, true, true, c);
Message m32 = ProviderTestUtils.setupMessage("1", b.mAccountKey, b.mId, true, true, c);
Message m33 = ProviderTestUtils.setupMessage("1", b.mAccountKey, b.mId, true, true, c);
// b4 has no messages.
// Check message counts
assertEquals(1, getMessageCount(b1.mId));
assertEquals(2, getMessageCount(b2.mId));
assertEquals(3, getMessageCount(b3.mId));
assertEquals(0, getMessageCount(b4.mId));
// 2. test for recalculateMessageCount.
// First, invalidate the message counts.
setMinusOneToMessageCounts();
assertEquals(-1, getMessageCount(b1.mId));
assertEquals(-1, getMessageCount(b2.mId));
assertEquals(-1, getMessageCount(b3.mId));
assertEquals(-1, getMessageCount(b4.mId));
// Batch update.
SQLiteDatabase db = getProvider().getDatabase(mMockContext);
EmailProvider.recalculateMessageCount(db);
// Check message counts
assertEquals(1, getMessageCount(b1.mId));
assertEquals(2, getMessageCount(b2.mId));
assertEquals(3, getMessageCount(b3.mId));
assertEquals(0, getMessageCount(b4.mId));
// 3. Check the "move mailbox" trigger.
// Move m32 (in mailbox 3) to mailbox 4.
ContentValues values = new ContentValues();
values.put(MessageColumns.MAILBOX_KEY, b4.mId);
getProvider().update(Message.CONTENT_URI, values, EmailContent.ID_SELECTION,
new String[] {"" + m32.mId});
// Check message counts
assertEquals(1, getMessageCount(b1.mId));
assertEquals(2, getMessageCount(b2.mId));
assertEquals(2, getMessageCount(b3.mId));
assertEquals(1, getMessageCount(b4.mId));
// 4. Check the delete trigger.
// Delete m11 (in mailbox 1)
getProvider().delete(Message.CONTENT_URI, EmailContent.ID_SELECTION,
new String[] {"" + m11.mId});
// Delete m21 (in mailbox 2)
getProvider().delete(Message.CONTENT_URI, EmailContent.ID_SELECTION,
new String[] {"" + m21.mId});
// Check message counts
assertEquals(0, getMessageCount(b1.mId));
assertEquals(1, getMessageCount(b2.mId));
assertEquals(2, getMessageCount(b3.mId));
assertEquals(1, getMessageCount(b4.mId));
}
}