diff --git a/src/com/android/email/provider/EmailContent.java b/src/com/android/email/provider/EmailContent.java index 776fd15f6..69680b35a 100644 --- a/src/com/android/email/provider/EmailContent.java +++ b/src/com/android/email/provider/EmailContent.java @@ -64,6 +64,8 @@ import java.util.UUID; public abstract class EmailContent { public static final String AUTHORITY = EmailProvider.EMAIL_AUTHORITY; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); + public static final String LIMIT_PARAMETER = "limit"; + // All classes share this public static final String RECORD_ID = "_id"; @@ -171,6 +173,11 @@ public abstract class EmailContent { return count(context, uri, null, null); } + static public Uri uriWithLimit(Uri uri, int limit) { + return uri.buildUpon().appendQueryParameter(EmailContent.LIMIT_PARAMETER, + Integer.toString(limit)).build(); + } + /** * no public constructor since this is a utility class */ diff --git a/src/com/android/email/provider/EmailProvider.java b/src/com/android/email/provider/EmailProvider.java index 2e64a2300..9a33e4754 100644 --- a/src/com/android/email/provider/EmailProvider.java +++ b/src/com/android/email/provider/EmailProvider.java @@ -1143,6 +1143,7 @@ public class EmailProvider extends ContentProvider { // See the comment at delete(), above SQLiteDatabase db = getDatabase(context); int table = match >> BASE_SHIFT; + String limit = uri.getQueryParameter(EmailContent.LIMIT_PARAMETER); String id; if (Email.LOGD) { @@ -1160,7 +1161,7 @@ public class EmailProvider extends ContentProvider { case ACCOUNT: case HOSTAUTH: c = db.query(TABLE_NAMES[table], projection, - selection, selectionArgs, null, null, sortOrder); + selection, selectionArgs, null, null, sortOrder, limit); break; case BODY_ID: case MESSAGE_ID: @@ -1172,14 +1173,15 @@ public class EmailProvider extends ContentProvider { case HOSTAUTH_ID: id = uri.getPathSegments().get(1); c = db.query(TABLE_NAMES[table], projection, - whereWithId(id, selection), selectionArgs, null, null, sortOrder); + whereWithId(id, selection), selectionArgs, null, null, sortOrder, + limit); break; case ATTACHMENTS_MESSAGE_ID: // All attachments for the given message id = uri.getPathSegments().get(2); c = db.query(Attachment.TABLE_NAME, projection, whereWith(Attachment.MESSAGE_KEY + "=" + id, selection), - selectionArgs, null, null, sortOrder); + selectionArgs, null, null, sortOrder, limit); break; default: throw new IllegalArgumentException("Unknown URI " + uri); diff --git a/tests/src/com/android/email/provider/ProviderTests.java b/tests/src/com/android/email/provider/ProviderTests.java index 8ceaab56a..4af4cea80 100644 --- a/tests/src/com/android/email/provider/ProviderTests.java +++ b/tests/src/com/android/email/provider/ProviderTests.java @@ -796,6 +796,59 @@ public class ProviderTests extends ProviderTestCase2 { assertNotNull(loadBodyForMessageId(message2Id)); } + /** + * Note that we can't use EmailContent.count() here because it uses a projection including + * count(*), and count(*) is incompatible with a LIMIT (i.e. the limit would be applied to the + * single column returned with count(*), rather than to the query itself) + */ + private int count(Context context, Uri uri, String selection, String[] selectionArgs) { + Cursor c = context.getContentResolver().query(uri, EmailContent.ID_PROJECTION, selection, + selectionArgs, null); + try { + return c.getCount(); + } finally { + c.close(); + } + } + + public void testMessageQueryWithLimit() { + final Context context = mMockContext; + + // Create account and two mailboxes + Account acct = ProviderTestUtils.setupAccount("orphaned body", true, context); + Mailbox box1 = ProviderTestUtils.setupMailbox("box1", acct.mId, true, context); + Mailbox box2 = ProviderTestUtils.setupMailbox("box2", acct.mId, true, context); + + // Create 4 messages in box1 + ProviderTestUtils.setupMessage("message1", acct.mId, box1.mId, false, true, context); + ProviderTestUtils.setupMessage("message2", acct.mId, box1.mId, false, true, context); + ProviderTestUtils.setupMessage("message3", acct.mId, box1.mId, false, true, context); + ProviderTestUtils.setupMessage("message4", acct.mId, box1.mId, false, true, context); + + // Create 4 messages in box2 + ProviderTestUtils.setupMessage("message1", acct.mId, box2.mId, false, true, context); + ProviderTestUtils.setupMessage("message2", acct.mId, box2.mId, false, true, context); + ProviderTestUtils.setupMessage("message3", acct.mId, box2.mId, false, true, context); + ProviderTestUtils.setupMessage("message4", acct.mId, box2.mId, false, true, context); + + // Check normal case, special case (limit 1), and arbitrary limits + assertEquals(8, count(mMockContext, Message.CONTENT_URI, null, null)); + assertEquals(1, count(mMockContext, EmailContent.uriWithLimit(Message.CONTENT_URI, 1), + null, null)); + assertEquals(3, count(mMockContext, EmailContent.uriWithLimit(Message.CONTENT_URI, 3), + null, null)); + assertEquals(8, count(mMockContext, EmailContent.uriWithLimit(Message.CONTENT_URI, 100), + null, null)); + + // Check that it works with selection/selection args + String[] args = new String[] {Long.toString(box1.mId)}; + assertEquals(4, count(mMockContext, Message.CONTENT_URI, + MessageColumns.MAILBOX_KEY + "=?", args)); + assertEquals(1, count(mMockContext, + EmailContent.uriWithLimit(Message.CONTENT_URI, 1), + MessageColumns.MAILBOX_KEY + "=?", args)); + } + /** * Test delete orphan messages * 1. create message without body (message id 1)