1f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler/* 2f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler * Copyright (C) 2009 The Android Open Source Project 3f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler * 4f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler * Licensed under the Apache License, Version 2.0 (the "License"); 5f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler * you may not use this file except in compliance with the License. 6f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler * You may obtain a copy of the License at 7f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler * 8f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler * http://www.apache.org/licenses/LICENSE-2.0 9f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler * 10f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler * Unless required by applicable law or agreed to in writing, software 11f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler * distributed under the License is distributed on an "AS IS" BASIS, 12f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler * See the License for the specific language governing permissions and 14f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler * limitations under the License. 15f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler */ 16f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 17f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadlerpackage com.android.email.provider; 18f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 19f33986d5cc248d2eeed0707143d81e94866f8e3aMihai Predaimport com.android.email.Email; 20a290f503f14432163f74548a5e5d1dc5003ad049Marc Blankimport com.android.email.provider.EmailContent.Account; 21a290f503f14432163f74548a5e5d1dc5003ad049Marc Blankimport com.android.email.provider.EmailContent.AccountColumns; 22a290f503f14432163f74548a5e5d1dc5003ad049Marc Blankimport com.android.email.provider.EmailContent.Attachment; 23a290f503f14432163f74548a5e5d1dc5003ad049Marc Blankimport com.android.email.provider.EmailContent.AttachmentColumns; 24a290f503f14432163f74548a5e5d1dc5003ad049Marc Blankimport com.android.email.provider.EmailContent.Body; 25a290f503f14432163f74548a5e5d1dc5003ad049Marc Blankimport com.android.email.provider.EmailContent.BodyColumns; 26a290f503f14432163f74548a5e5d1dc5003ad049Marc Blankimport com.android.email.provider.EmailContent.HostAuth; 27a290f503f14432163f74548a5e5d1dc5003ad049Marc Blankimport com.android.email.provider.EmailContent.HostAuthColumns; 28a290f503f14432163f74548a5e5d1dc5003ad049Marc Blankimport com.android.email.provider.EmailContent.Mailbox; 29a290f503f14432163f74548a5e5d1dc5003ad049Marc Blankimport com.android.email.provider.EmailContent.MailboxColumns; 30a290f503f14432163f74548a5e5d1dc5003ad049Marc Blankimport com.android.email.provider.EmailContent.Message; 31a290f503f14432163f74548a5e5d1dc5003ad049Marc Blankimport com.android.email.provider.EmailContent.MessageColumns; 32a290f503f14432163f74548a5e5d1dc5003ad049Marc Blankimport com.android.email.provider.EmailContent.SyncColumns; 33f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 34e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blankimport android.accounts.AccountManager; 35f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadlerimport android.content.ContentProvider; 36fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blankimport android.content.ContentProviderOperation; 37fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blankimport android.content.ContentProviderResult; 38f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadlerimport android.content.ContentUris; 39f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadlerimport android.content.ContentValues; 40f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadlerimport android.content.Context; 41fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blankimport android.content.OperationApplicationException; 42f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadlerimport android.content.UriMatcher; 43f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadlerimport android.database.Cursor; 44a290f503f14432163f74548a5e5d1dc5003ad049Marc Blankimport android.database.SQLException; 45f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadlerimport android.database.sqlite.SQLiteDatabase; 460e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blankimport android.database.sqlite.SQLiteException; 47f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadlerimport android.database.sqlite.SQLiteOpenHelper; 48f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadlerimport android.net.Uri; 49f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadlerimport android.util.Log; 50f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 510e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blankimport java.io.File; 5284969fb580f569c0e3625a3c59a71d2909ae198dFred Quintanaimport java.util.ArrayList; 5384969fb580f569c0e3625a3c59a71d2909ae198dFred Quintana 54f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadlerpublic class EmailProvider extends ContentProvider { 55f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 56f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final String TAG = "EmailProvider"; 57f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 580e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank protected static final String DATABASE_NAME = "EmailProvider.db"; 590e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank protected static final String BODY_DATABASE_NAME = "EmailProviderBody.db"; 600e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank 610e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank public static final Uri INTEGRITY_CHECK_URI = 620e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank Uri.parse("content://" + EmailContent.AUTHORITY + "/integrityCheck"); 63ef83299b99288c00b9d661260d19715e73e6889cMarc Blank 64ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // Definitions for our queries looking for orphaned messages 65ef83299b99288c00b9d661260d19715e73e6889cMarc Blank private static final String[] ORPHANS_PROJECTION 66ef83299b99288c00b9d661260d19715e73e6889cMarc Blank = new String[] {MessageColumns.ID, MessageColumns.MAILBOX_KEY}; 67ef83299b99288c00b9d661260d19715e73e6889cMarc Blank private static final int ORPHANS_ID = 0; 68ef83299b99288c00b9d661260d19715e73e6889cMarc Blank private static final int ORPHANS_MAILBOX_KEY = 1; 69ef83299b99288c00b9d661260d19715e73e6889cMarc Blank 70ef83299b99288c00b9d661260d19715e73e6889cMarc Blank private static final String WHERE_ID = EmailContent.RECORD_ID + "=?"; 71f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 724a8c70c09be3914ded18031b4cca5a6d867de0d3Andrew Stadler // Any changes to the database format *must* include update-in-place code. 73e25698319325d5e9619bc45ae85d861b0f1c5954Marc Blank // Original version: 3 74e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank // Version 4: Database wipe required; changing AccountManager interface w/Exchange 750d00889f83fc8c1d69039a2c849b630fb4dd28ddAndrew Stadler // Version 5: Database wipe required; changing AccountManager interface w/Exchange 760d00889f83fc8c1d69039a2c849b630fb4dd28ddAndrew Stadler // Version 6: Adding Message.mServerTimeStamp column 77ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // Version 7: Replace the mailbox_delete trigger with a version that removes orphaned messages 78ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // from the Message_Deletes and Message_Updates tables 79fc8d943a828cd79ff71c703ced37001bd5482173Andrew Stadler // Version 8: Add security flags column to accounts table 80345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler // Version 9: Add security sync key and signature to accounts table 814006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank // Version 10: Add meeting info to message table 823aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler // Version 11: Add content and flags to attachment table 8320225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki // Version 12: Add content_bytes to attachment table. content is deprecated. 8420225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki public static final int DATABASE_VERSION = 12; 85e25698319325d5e9619bc45ae85d861b0f1c5954Marc Blank 86e25698319325d5e9619bc45ae85d861b0f1c5954Marc Blank // Any changes to the database format *must* include update-in-place code. 87e25698319325d5e9619bc45ae85d861b0f1c5954Marc Blank // Original version: 2 88e25698319325d5e9619bc45ae85d861b0f1c5954Marc Blank // Version 3: Add "sourceKey" column 89e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank // Version 4: Database wipe required; changing AccountManager interface w/Exchange 900d00889f83fc8c1d69039a2c849b630fb4dd28ddAndrew Stadler // Version 5: Database wipe required; changing AccountManager interface w/Exchange 915fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank // Version 6: Adding Body.mIntroText column 925fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank public static final int BODY_DATABASE_VERSION = 6; 93f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 94a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank public static final String EMAIL_AUTHORITY = "com.android.email.provider"; 95f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 96f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int ACCOUNT_BASE = 0; 97f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int ACCOUNT = ACCOUNT_BASE; 98f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int ACCOUNT_MAILBOXES = ACCOUNT_BASE + 1; 99f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int ACCOUNT_ID = ACCOUNT_BASE + 2; 100c0c9c33322deecace00a32766e0a1b355aad4b31Marc Blank private static final int ACCOUNT_ID_ADD_TO_FIELD = ACCOUNT_BASE + 3; 101f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 102f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int MAILBOX_BASE = 0x1000; 103f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int MAILBOX = MAILBOX_BASE; 104f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int MAILBOX_MESSAGES = MAILBOX_BASE + 1; 105f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int MAILBOX_ID = MAILBOX_BASE + 2; 106c0c9c33322deecace00a32766e0a1b355aad4b31Marc Blank private static final int MAILBOX_ID_ADD_TO_FIELD = MAILBOX_BASE + 3; 107f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 108f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int MESSAGE_BASE = 0x2000; 109f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int MESSAGE = MESSAGE_BASE; 1104119218e2fd64341ac946fb8f2cbdb796a444cb8Andrew Stadler private static final int MESSAGE_ID = MESSAGE_BASE + 1; 1114119218e2fd64341ac946fb8f2cbdb796a444cb8Andrew Stadler private static final int SYNCED_MESSAGE_ID = MESSAGE_BASE + 2; 112f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 113f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int ATTACHMENT_BASE = 0x3000; 114f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int ATTACHMENT = ATTACHMENT_BASE; 115f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int ATTACHMENT_CONTENT = ATTACHMENT_BASE + 1; 116f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int ATTACHMENT_ID = ATTACHMENT_BASE + 2; 1174119218e2fd64341ac946fb8f2cbdb796a444cb8Andrew Stadler private static final int ATTACHMENTS_MESSAGE_ID = ATTACHMENT_BASE + 3; 118f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 119f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int HOSTAUTH_BASE = 0x4000; 120f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int HOSTAUTH = HOSTAUTH_BASE; 121f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int HOSTAUTH_ID = HOSTAUTH_BASE + 1; 122f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 123e34525d0f026a7467cee1cb5fddcf25ba6f35207Marc Blank private static final int UPDATED_MESSAGE_BASE = 0x5000; 124e34525d0f026a7467cee1cb5fddcf25ba6f35207Marc Blank private static final int UPDATED_MESSAGE = UPDATED_MESSAGE_BASE; 125f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank private static final int UPDATED_MESSAGE_ID = UPDATED_MESSAGE_BASE + 1; 126f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 127f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank private static final int DELETED_MESSAGE_BASE = 0x6000; 128f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank private static final int DELETED_MESSAGE = DELETED_MESSAGE_BASE; 129f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank private static final int DELETED_MESSAGE_ID = DELETED_MESSAGE_BASE + 1; 130f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank private static final int DELETED_MESSAGE_MAILBOX = DELETED_MESSAGE_BASE + 2; 131f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 132f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank // MUST ALWAYS EQUAL THE LAST OF THE PREVIOUS BASE CONSTANTS 133f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank private static final int LAST_EMAIL_PROVIDER_DB_BASE = DELETED_MESSAGE_BASE; 134f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 135f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank // DO NOT CHANGE BODY_BASE!! 136f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank private static final int BODY_BASE = LAST_EMAIL_PROVIDER_DB_BASE + 0x1000; 137f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int BODY = BODY_BASE; 138f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int BODY_ID = BODY_BASE + 1; 13933e176f4919569a9444d641e94034785c10c5562Marc Blank private static final int BODY_MESSAGE_ID = BODY_BASE + 2; 14033e176f4919569a9444d641e94034785c10c5562Marc Blank private static final int BODY_HTML = BODY_BASE + 3; 141f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int BODY_TEXT = BODY_BASE + 4; 142f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 143f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 144f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final int BASE_SHIFT = 12; // 12 bits to the base type: 0, 0x1000, 0x2000, etc. 145f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 146f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final String[] TABLE_NAMES = { 147a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank EmailContent.Account.TABLE_NAME, 148a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank EmailContent.Mailbox.TABLE_NAME, 149a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank EmailContent.Message.TABLE_NAME, 150a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank EmailContent.Attachment.TABLE_NAME, 151a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank EmailContent.HostAuth.TABLE_NAME, 152f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank EmailContent.Message.UPDATED_TABLE_NAME, 153f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank EmailContent.Message.DELETED_TABLE_NAME, 154a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank EmailContent.Body.TABLE_NAME 155f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler }; 156f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 157f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); 158f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 159f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank /** 160f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank * Let's only generate these SQL strings once, as they are used frequently 161f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank * Note that this isn't relevant for table creation strings, since they are used only once 162f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank */ 163f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank private static final String UPDATED_MESSAGE_INSERT = "insert or ignore into " + 164f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank Message.UPDATED_TABLE_NAME + " select * from " + Message.TABLE_NAME + " where " + 165f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank EmailContent.RECORD_ID + '='; 166f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 167f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank private static final String UPDATED_MESSAGE_DELETE = "delete from " + 168f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank Message.UPDATED_TABLE_NAME + " where " + EmailContent.RECORD_ID + '='; 169f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 170f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank private static final String DELETED_MESSAGE_INSERT = "insert or replace into " + 171f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank Message.DELETED_TABLE_NAME + " select * from " + Message.TABLE_NAME + " where " + 172f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank EmailContent.RECORD_ID + '='; 173f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 174f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank private static final String DELETE_ORPHAN_BODIES = "delete from " + Body.TABLE_NAME + 175fb7974f5bfb6275fb856b0f7ff386ef10680c83aMihai Preda " where " + BodyColumns.MESSAGE_KEY + " in " + "(select " + BodyColumns.MESSAGE_KEY + 176f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank " from " + Body.TABLE_NAME + " except select " + EmailContent.RECORD_ID + " from " + 177f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank Message.TABLE_NAME + ')'; 178f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 179f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank private static final String DELETE_BODY = "delete from " + Body.TABLE_NAME + 180fb7974f5bfb6275fb856b0f7ff386ef10680c83aMihai Preda " where " + BodyColumns.MESSAGE_KEY + '='; 181f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 182c0c9c33322deecace00a32766e0a1b355aad4b31Marc Blank private static final String ID_EQUALS = EmailContent.RECORD_ID + "=?"; 183c0c9c33322deecace00a32766e0a1b355aad4b31Marc Blank 184ef83299b99288c00b9d661260d19715e73e6889cMarc Blank private static final String TRIGGER_MAILBOX_DELETE = 185ef83299b99288c00b9d661260d19715e73e6889cMarc Blank "create trigger mailbox_delete before delete on " + Mailbox.TABLE_NAME + 186ef83299b99288c00b9d661260d19715e73e6889cMarc Blank " begin" + 187ef83299b99288c00b9d661260d19715e73e6889cMarc Blank " delete from " + Message.TABLE_NAME + 188ef83299b99288c00b9d661260d19715e73e6889cMarc Blank " where " + MessageColumns.MAILBOX_KEY + "=old." + EmailContent.RECORD_ID + 189ef83299b99288c00b9d661260d19715e73e6889cMarc Blank "; delete from " + Message.UPDATED_TABLE_NAME + 190ef83299b99288c00b9d661260d19715e73e6889cMarc Blank " where " + MessageColumns.MAILBOX_KEY + "=old." + EmailContent.RECORD_ID + 191ef83299b99288c00b9d661260d19715e73e6889cMarc Blank "; delete from " + Message.DELETED_TABLE_NAME + 192ef83299b99288c00b9d661260d19715e73e6889cMarc Blank " where " + MessageColumns.MAILBOX_KEY + "=old." + EmailContent.RECORD_ID + 193ef83299b99288c00b9d661260d19715e73e6889cMarc Blank "; end"; 194367963639d4291511b7e175a208e2b553aac26c2Marc Blank 195f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler static { 196f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // Email URI matching table 197f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler UriMatcher matcher = sURIMatcher; 198f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 199f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // All accounts 200f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank matcher.addURI(EMAIL_AUTHORITY, "account", ACCOUNT); 201f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // A specific account 202758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank // insert into this URI causes a mailbox to be added to the account 203f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank matcher.addURI(EMAIL_AUTHORITY, "account/#", ACCOUNT_ID); 204f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // The mailboxes in a specific account 205f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler matcher.addURI(EMAIL_AUTHORITY, "account/#/mailbox", ACCOUNT_MAILBOXES); 206f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 207f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // All mailboxes 208f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank matcher.addURI(EMAIL_AUTHORITY, "mailbox", MAILBOX); 209f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // A specific mailbox 210f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // insert into this URI causes a message to be added to the mailbox 211f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // ** NOTE For now, the accountKey must be set manually in the values! 212f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank matcher.addURI(EMAIL_AUTHORITY, "mailbox/#", MAILBOX_ID); 213f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // The messages in a specific mailbox 214f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler matcher.addURI(EMAIL_AUTHORITY, "mailbox/#/message", MAILBOX_MESSAGES); 215f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 216f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // All messages 217f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank matcher.addURI(EMAIL_AUTHORITY, "message", MESSAGE); 218f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // A specific message 219758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank // insert into this URI causes an attachment to be added to the message 220f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank matcher.addURI(EMAIL_AUTHORITY, "message/#", MESSAGE_ID); 221f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 222f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // A specific attachment 223f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank matcher.addURI(EMAIL_AUTHORITY, "attachment", ATTACHMENT); 224f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // A specific attachment (the header information) 225f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank matcher.addURI(EMAIL_AUTHORITY, "attachment/#", ATTACHMENT_ID); 226f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // The content for a specific attachment 227f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank // NOT IMPLEMENTED 228f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler matcher.addURI(EMAIL_AUTHORITY, "attachment/content/*", ATTACHMENT_CONTENT); 2294119218e2fd64341ac946fb8f2cbdb796a444cb8Andrew Stadler // The attachments of a specific message (query only) (insert & delete TBD) 2304119218e2fd64341ac946fb8f2cbdb796a444cb8Andrew Stadler matcher.addURI(EMAIL_AUTHORITY, "attachment/message/#", ATTACHMENTS_MESSAGE_ID); 231f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 232f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // All mail bodies 233f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler matcher.addURI(EMAIL_AUTHORITY, "body", BODY); 234f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // A specific mail body 235f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler matcher.addURI(EMAIL_AUTHORITY, "body/#", BODY_ID); 23633e176f4919569a9444d641e94034785c10c5562Marc Blank // The body for a specific message 23733e176f4919569a9444d641e94034785c10c5562Marc Blank matcher.addURI(EMAIL_AUTHORITY, "body/message/#", BODY_MESSAGE_ID); 238f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // The HTML part of a specific mail body 239f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler matcher.addURI(EMAIL_AUTHORITY, "body/#/html", BODY_HTML); 240f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // The plain text part of a specific mail body 241f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler matcher.addURI(EMAIL_AUTHORITY, "body/#/text", BODY_TEXT); 242f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 2434119218e2fd64341ac946fb8f2cbdb796a444cb8Andrew Stadler // All hostauth records 2444119218e2fd64341ac946fb8f2cbdb796a444cb8Andrew Stadler matcher.addURI(EMAIL_AUTHORITY, "hostauth", HOSTAUTH); 2454119218e2fd64341ac946fb8f2cbdb796a444cb8Andrew Stadler // A specific hostauth 2464119218e2fd64341ac946fb8f2cbdb796a444cb8Andrew Stadler matcher.addURI(EMAIL_AUTHORITY, "hostauth/#", HOSTAUTH_ID); 247f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 248c0c9c33322deecace00a32766e0a1b355aad4b31Marc Blank // Atomically a constant value to a particular field of a mailbox/account 249c0c9c33322deecace00a32766e0a1b355aad4b31Marc Blank matcher.addURI(EMAIL_AUTHORITY, "mailboxIdAddToField/#", MAILBOX_ID_ADD_TO_FIELD); 250c0c9c33322deecace00a32766e0a1b355aad4b31Marc Blank matcher.addURI(EMAIL_AUTHORITY, "accountIdAddToField/#", ACCOUNT_ID_ADD_TO_FIELD); 251c0c9c33322deecace00a32766e0a1b355aad4b31Marc Blank 252f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank /** 253f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank * THIS URI HAS SPECIAL SEMANTICS 254c0c9c33322deecace00a32766e0a1b355aad4b31Marc Blank * ITS USE IS INTENDED FOR THE UI APPLICATION TO MARK CHANGES THAT NEED TO BE SYNCED BACK 255f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank * TO A SERVER VIA A SYNC ADAPTER 256f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank */ 257f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank matcher.addURI(EMAIL_AUTHORITY, "syncedMessage/#", SYNCED_MESSAGE_ID); 258f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 259f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank /** 260f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank * THE URIs BELOW THIS POINT ARE INTENDED TO BE USED BY SYNC ADAPTERS ONLY 261f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank * THEY REFER TO DATA CREATED AND MAINTAINED BY CALLS TO THE SYNCED_MESSAGE_ID URI 262f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank * BY THE UI APPLICATION 263f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank */ 264f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank // All deleted messages 265f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank matcher.addURI(EMAIL_AUTHORITY, "deletedMessage", DELETED_MESSAGE); 266f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank // A specific deleted message 267f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank matcher.addURI(EMAIL_AUTHORITY, "deletedMessage/#", DELETED_MESSAGE_ID); 268f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank // All deleted messages from a specific mailbox 269f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank // NOT IMPLEMENTED; do we need this as a convenience? 270f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank matcher.addURI(EMAIL_AUTHORITY, "deletedMessage/mailbox/#", DELETED_MESSAGE_MAILBOX); 271f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 272f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank // All updated messages 273f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank matcher.addURI(EMAIL_AUTHORITY, "updatedMessage", UPDATED_MESSAGE); 274f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank // A specific updated message 275f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank matcher.addURI(EMAIL_AUTHORITY, "updatedMessage/#", UPDATED_MESSAGE_ID); 276f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 277f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 2789627d014e16235eadf981b9165807dc72a14a383Mihai Preda /* 2799627d014e16235eadf981b9165807dc72a14a383Mihai Preda * Internal helper method for index creation. 2809627d014e16235eadf981b9165807dc72a14a383Mihai Preda * Example: 2819627d014e16235eadf981b9165807dc72a14a383Mihai Preda * "create index message_" + MessageColumns.FLAG_READ 2829627d014e16235eadf981b9165807dc72a14a383Mihai Preda * + " on " + Message.TABLE_NAME + " (" + MessageColumns.FLAG_READ + ");" 2839627d014e16235eadf981b9165807dc72a14a383Mihai Preda */ 2849627d014e16235eadf981b9165807dc72a14a383Mihai Preda /* package */ 2859627d014e16235eadf981b9165807dc72a14a383Mihai Preda static String createIndex(String tableName, String columnName) { 2869627d014e16235eadf981b9165807dc72a14a383Mihai Preda return "create index " + tableName.toLowerCase() + '_' + columnName 2879627d014e16235eadf981b9165807dc72a14a383Mihai Preda + " on " + tableName + " (" + columnName + ");"; 2889627d014e16235eadf981b9165807dc72a14a383Mihai Preda } 2899627d014e16235eadf981b9165807dc72a14a383Mihai Preda 290a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank static void createMessageTable(SQLiteDatabase db) { 291b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank String messageColumns = MessageColumns.DISPLAY_NAME + " text, " 292b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.TIMESTAMP + " integer, " 293b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.SUBJECT + " text, " 294b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.FLAG_READ + " integer, " 295b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.FLAG_LOADED + " integer, " 296b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.FLAG_FAVORITE + " integer, " 297b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.FLAG_ATTACHMENT + " integer, " 298b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.FLAGS + " integer, " 299b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.CLIENT_ID + " integer, " 300b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.MESSAGE_ID + " text, " 301b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.MAILBOX_KEY + " integer, " 302b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.ACCOUNT_KEY + " integer, " 303b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.FROM_LIST + " text, " 304b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.TO_LIST + " text, " 305b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.CC_LIST + " text, " 306b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + MessageColumns.BCC_LIST + " text, " 3074006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank + MessageColumns.REPLY_TO_LIST + " text, " 3084006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank + MessageColumns.MEETING_INFO + " text" 309b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + ");"; 310b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank 311b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank // This String and the following String MUST have the same columns, except for the type 312b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank // of those columns! 313b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank String createString = " (" + EmailContent.RECORD_ID + " integer primary key autoincrement, " 3140d00889f83fc8c1d69039a2c849b630fb4dd28ddAndrew Stadler + SyncColumns.SERVER_ID + " text, " 3150d00889f83fc8c1d69039a2c849b630fb4dd28ddAndrew Stadler + SyncColumns.SERVER_TIMESTAMP + " integer, " 316b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + messageColumns; 317b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank 318b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank // For the updated and deleted tables, the id is assigned, but we do want to keep track 319b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank // of the ORDER of updates using an autoincrement primary key. We use the DATA column 320b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank // at this point; it has no other function 3216b158f715b2ab6b2f35e894857446023f1d8be88Marc Blank String altCreateString = " (" + EmailContent.RECORD_ID + " integer unique, " 3220d00889f83fc8c1d69039a2c849b630fb4dd28ddAndrew Stadler + SyncColumns.SERVER_ID + " text, " 3230d00889f83fc8c1d69039a2c849b630fb4dd28ddAndrew Stadler + SyncColumns.SERVER_TIMESTAMP + " integer, " 324b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + messageColumns; 325f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 326f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank // The three tables have the same schema 327b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank db.execSQL("create table " + Message.TABLE_NAME + createString); 328b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank db.execSQL("create table " + Message.UPDATED_TABLE_NAME + altCreateString); 329b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank db.execSQL("create table " + Message.DELETED_TABLE_NAME + altCreateString); 330f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 3319627d014e16235eadf981b9165807dc72a14a383Mihai Preda String indexColumns[] = { 3329627d014e16235eadf981b9165807dc72a14a383Mihai Preda MessageColumns.TIMESTAMP, 3339627d014e16235eadf981b9165807dc72a14a383Mihai Preda MessageColumns.FLAG_READ, 3349627d014e16235eadf981b9165807dc72a14a383Mihai Preda MessageColumns.FLAG_LOADED, 3359627d014e16235eadf981b9165807dc72a14a383Mihai Preda MessageColumns.MAILBOX_KEY, 3369627d014e16235eadf981b9165807dc72a14a383Mihai Preda SyncColumns.SERVER_ID 3379627d014e16235eadf981b9165807dc72a14a383Mihai Preda }; 3389627d014e16235eadf981b9165807dc72a14a383Mihai Preda 3399627d014e16235eadf981b9165807dc72a14a383Mihai Preda for (String columnName : indexColumns) { 3409627d014e16235eadf981b9165807dc72a14a383Mihai Preda db.execSQL(createIndex(Message.TABLE_NAME, columnName)); 3419627d014e16235eadf981b9165807dc72a14a383Mihai Preda } 3422c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank 343f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank // Deleting a Message deletes all associated Attachments 3442c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank // Deleting the associated Body cannot be done in a trigger, because the Body is stored 3452c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank // in a separate database, and trigger cannot operate on attached databases. 346758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank db.execSQL("create trigger message_delete before delete on " + Message.TABLE_NAME + 3472c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank " begin delete from " + Attachment.TABLE_NAME + 348758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " where " + AttachmentColumns.MESSAGE_KEY + "=old." + EmailContent.RECORD_ID + 349758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank "; end"); 350758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank 351758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank // Add triggers to keep unread count accurate per mailbox 352758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank 353758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank // Insert a message; if flagRead is zero, add to the unread count of the message's mailbox 354758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank db.execSQL("create trigger unread_message_insert before insert on " + Message.TABLE_NAME + 355758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " when NEW." + MessageColumns.FLAG_READ + "=0" + 356758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " begin update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.UNREAD_COUNT + 357758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank '=' + MailboxColumns.UNREAD_COUNT + "+1" + 358758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " where " + EmailContent.RECORD_ID + "=NEW." + MessageColumns.MAILBOX_KEY + 359758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank "; end"); 360758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank 361758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank // Delete a message; if flagRead is zero, decrement the unread count of the msg's mailbox 362758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank db.execSQL("create trigger unread_message_delete before delete on " + Message.TABLE_NAME + 363758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " when OLD." + MessageColumns.FLAG_READ + "=0" + 364758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " begin update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.UNREAD_COUNT + 365758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank '=' + MailboxColumns.UNREAD_COUNT + "-1" + 366758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " where " + EmailContent.RECORD_ID + "=OLD." + MessageColumns.MAILBOX_KEY + 367758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank "; end"); 368758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank 369758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank // Change a message's mailbox 370758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank db.execSQL("create trigger unread_message_move before update of " + 371758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank MessageColumns.MAILBOX_KEY + " on " + Message.TABLE_NAME + 372758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " when OLD." + MessageColumns.FLAG_READ + "=0" + 373758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " begin update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.UNREAD_COUNT + 374758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank '=' + MailboxColumns.UNREAD_COUNT + "-1" + 375758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " where " + EmailContent.RECORD_ID + "=OLD." + MessageColumns.MAILBOX_KEY + 376758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank "; update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.UNREAD_COUNT + 377758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank '=' + MailboxColumns.UNREAD_COUNT + "+1" + 378758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " where " + EmailContent.RECORD_ID + "=NEW." + MessageColumns.MAILBOX_KEY + 379758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank "; end"); 380758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank 381758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank // Change a message's read state 382b720ed318324c69ddbcb15c4a1b9e132f3266775Vasu Nori db.execSQL("create trigger unread_message_read before update of " + 383758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank MessageColumns.FLAG_READ + " on " + Message.TABLE_NAME + 384758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " when OLD." + MessageColumns.FLAG_READ + "!=NEW." + MessageColumns.FLAG_READ + 385758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " begin update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.UNREAD_COUNT + 386758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank '=' + MailboxColumns.UNREAD_COUNT + "+ case OLD." + MessageColumns.FLAG_READ + 387758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " when 0 then -1 else 1 end" + 388758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " where " + EmailContent.RECORD_ID + "=OLD." + MessageColumns.MAILBOX_KEY + 389758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank "; end"); 390758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank } 391a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 392e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank static void resetMessageTable(SQLiteDatabase db, int oldVersion, int newVersion) { 393ddc871d9eddd088c0200a30dbfeb24812a81cf80Andrew Stadler try { 394ddc871d9eddd088c0200a30dbfeb24812a81cf80Andrew Stadler db.execSQL("drop table " + Message.TABLE_NAME); 395ddc871d9eddd088c0200a30dbfeb24812a81cf80Andrew Stadler db.execSQL("drop table " + Message.UPDATED_TABLE_NAME); 396ddc871d9eddd088c0200a30dbfeb24812a81cf80Andrew Stadler db.execSQL("drop table " + Message.DELETED_TABLE_NAME); 397ddc871d9eddd088c0200a30dbfeb24812a81cf80Andrew Stadler } catch (SQLException e) { 398ddc871d9eddd088c0200a30dbfeb24812a81cf80Andrew Stadler } 399a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank createMessageTable(db); 400a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 401a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 402a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank static void createAccountTable(SQLiteDatabase db) { 403758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank String s = " (" + EmailContent.RECORD_ID + " integer primary key autoincrement, " 404a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AccountColumns.DISPLAY_NAME + " text, " 405a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AccountColumns.EMAIL_ADDRESS + " text, " 406a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AccountColumns.SYNC_KEY + " text, " 407a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AccountColumns.SYNC_LOOKBACK + " integer, " 4089e2c6bd5f21f2d19eef7ebfe30e6fdf94ede0857Andrew Stadler + AccountColumns.SYNC_INTERVAL + " text, " 409a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AccountColumns.HOST_AUTH_KEY_RECV + " integer, " 410a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AccountColumns.HOST_AUTH_KEY_SEND + " integer, " 411a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AccountColumns.FLAGS + " integer, " 412a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AccountColumns.IS_DEFAULT + " integer, " 413a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AccountColumns.COMPATIBILITY_UUID + " text, " 414a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AccountColumns.SENDER_NAME + " text, " 41553093871c492d03947c494f17e2463b27345e083Marc Blank + AccountColumns.RINGTONE_URI + " text, " 4164a8c70c09be3914ded18031b4cca5a6d867de0d3Andrew Stadler + AccountColumns.PROTOCOL_VERSION + " text, " 417fc8d943a828cd79ff71c703ced37001bd5482173Andrew Stadler + AccountColumns.NEW_MESSAGE_COUNT + " integer, " 418345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler + AccountColumns.SECURITY_FLAGS + " integer, " 419345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler + AccountColumns.SECURITY_SYNC_KEY + " text, " 420345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler + AccountColumns.SIGNATURE + " text " 421a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + ");"; 422a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank db.execSQL("create table " + Account.TABLE_NAME + s); 4232c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank // Deleting an account deletes associated Mailboxes and HostAuth's 424b720ed318324c69ddbcb15c4a1b9e132f3266775Vasu Nori db.execSQL("create trigger account_delete before delete on " + Account.TABLE_NAME + 4252c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank " begin delete from " + Mailbox.TABLE_NAME + 426758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank " where " + MailboxColumns.ACCOUNT_KEY + "=old." + EmailContent.RECORD_ID + 4272c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank "; delete from " + HostAuth.TABLE_NAME + 428f00dccd32125c727cc18d837b59c15c95f5d78bcMarc Blank " where " + EmailContent.RECORD_ID + "=old." + AccountColumns.HOST_AUTH_KEY_RECV + 429f00dccd32125c727cc18d837b59c15c95f5d78bcMarc Blank "; delete from " + HostAuth.TABLE_NAME + 430f00dccd32125c727cc18d837b59c15c95f5d78bcMarc Blank " where " + EmailContent.RECORD_ID + "=old." + AccountColumns.HOST_AUTH_KEY_SEND + 431f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank "; end"); 432f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank } 433a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 434e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank static void resetAccountTable(SQLiteDatabase db, int oldVersion, int newVersion) { 435a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank try { 436a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank db.execSQL("drop table " + Account.TABLE_NAME); 437a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } catch (SQLException e) { 438a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 439a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank createAccountTable(db); 440a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 441f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 442a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank static void createHostAuthTable(SQLiteDatabase db) { 443758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank String s = " (" + EmailContent.RECORD_ID + " integer primary key autoincrement, " 444a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + HostAuthColumns.PROTOCOL + " text, " 445a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + HostAuthColumns.ADDRESS + " text, " 446a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + HostAuthColumns.PORT + " integer, " 447a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + HostAuthColumns.FLAGS + " integer, " 448a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + HostAuthColumns.LOGIN + " text, " 449a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + HostAuthColumns.PASSWORD + " text, " 450a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + HostAuthColumns.DOMAIN + " text, " 451a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + HostAuthColumns.ACCOUNT_KEY + " integer" 452a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + ");"; 453a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank db.execSQL("create table " + HostAuth.TABLE_NAME + s); 454a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 455a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 456e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank static void resetHostAuthTable(SQLiteDatabase db, int oldVersion, int newVersion) { 457a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank try { 458a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank db.execSQL("drop table " + HostAuth.TABLE_NAME); 459a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } catch (SQLException e) { 460a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 461a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank createHostAuthTable(db); 462a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 463a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 464f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank static void createMailboxTable(SQLiteDatabase db) { 465758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank String s = " (" + EmailContent.RECORD_ID + " integer primary key autoincrement, " 466a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + MailboxColumns.DISPLAY_NAME + " text, " 4679be10e62ed4c809c56e2bcc357d5bb7d5dd543c1Marc Blank + MailboxColumns.SERVER_ID + " text, " 468a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + MailboxColumns.PARENT_SERVER_ID + " text, " 469a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + MailboxColumns.ACCOUNT_KEY + " integer, " 470a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + MailboxColumns.TYPE + " integer, " 471a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + MailboxColumns.DELIMITER + " integer, " 472a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + MailboxColumns.SYNC_KEY + " text, " 473a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + MailboxColumns.SYNC_LOOKBACK + " integer, " 4749e2c6bd5f21f2d19eef7ebfe30e6fdf94ede0857Andrew Stadler + MailboxColumns.SYNC_INTERVAL + " integer, " 475a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + MailboxColumns.SYNC_TIME + " integer, " 476a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + MailboxColumns.UNREAD_COUNT + " integer, " 477a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + MailboxColumns.FLAG_VISIBLE + " integer, " 478a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + MailboxColumns.FLAGS + " integer, " 4799b598924ec1dd53f865a6aa552d40161aeb5dd0bMarc Blank + MailboxColumns.VISIBLE_LIMIT + " integer, " 4809b598924ec1dd53f865a6aa552d40161aeb5dd0bMarc Blank + MailboxColumns.SYNC_STATUS + " text" 481b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank + ");"; 482f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank db.execSQL("create table " + Mailbox.TABLE_NAME + s); 483758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank db.execSQL("create index mailbox_" + MailboxColumns.SERVER_ID 484a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + " on " + Mailbox.TABLE_NAME + " (" + MailboxColumns.SERVER_ID + ")"); 485758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank db.execSQL("create index mailbox_" + MailboxColumns.ACCOUNT_KEY 486a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + " on " + Mailbox.TABLE_NAME + " (" + MailboxColumns.ACCOUNT_KEY + ")"); 487ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // Deleting a Mailbox deletes associated Messages in all three tables 488ef83299b99288c00b9d661260d19715e73e6889cMarc Blank db.execSQL(TRIGGER_MAILBOX_DELETE); 489a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 490a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 491e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank static void resetMailboxTable(SQLiteDatabase db, int oldVersion, int newVersion) { 492a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank try { 493a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank db.execSQL("drop table " + Mailbox.TABLE_NAME); 494a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } catch (SQLException e) { 495a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 496a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank createMailboxTable(db); 497a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 498f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 499a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank static void createAttachmentTable(SQLiteDatabase db) { 500758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank String s = " (" + EmailContent.RECORD_ID + " integer primary key autoincrement, " 501a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AttachmentColumns.FILENAME + " text, " 502a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AttachmentColumns.MIME_TYPE + " text, " 503a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AttachmentColumns.SIZE + " integer, " 504a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AttachmentColumns.CONTENT_ID + " text, " 505a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AttachmentColumns.CONTENT_URI + " text, " 506a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AttachmentColumns.MESSAGE_KEY + " integer, " 507a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + AttachmentColumns.LOCATION + " text, " 5083aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler + AttachmentColumns.ENCODING + " text, " 5093aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler + AttachmentColumns.CONTENT + " text, " 51020225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki + AttachmentColumns.FLAGS + " integer, " 51120225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki + AttachmentColumns.CONTENT_BYTES + " blob" 512a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + ");"; 513a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank db.execSQL("create table " + Attachment.TABLE_NAME + s); 5149627d014e16235eadf981b9165807dc72a14a383Mihai Preda db.execSQL(createIndex(Attachment.TABLE_NAME, AttachmentColumns.MESSAGE_KEY)); 515a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 516a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 517e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank static void resetAttachmentTable(SQLiteDatabase db, int oldVersion, int newVersion) { 518a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank try { 519a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank db.execSQL("drop table " + Attachment.TABLE_NAME); 520a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } catch (SQLException e) { 521a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 522a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank createAttachmentTable(db); 523a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 524a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 525a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank static void createBodyTable(SQLiteDatabase db) { 526758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank String s = " (" + EmailContent.RECORD_ID + " integer primary key autoincrement, " 527a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + BodyColumns.MESSAGE_KEY + " integer, " 528a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + BodyColumns.HTML_CONTENT + " text, " 529936babc145e2e6eb2e222f2ce5e3da8f9e4fb9f2Andrew Stadler + BodyColumns.TEXT_CONTENT + " text, " 530936babc145e2e6eb2e222f2ce5e3da8f9e4fb9f2Andrew Stadler + BodyColumns.HTML_REPLY + " text, " 531e25698319325d5e9619bc45ae85d861b0f1c5954Marc Blank + BodyColumns.TEXT_REPLY + " text, " 5325fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank + BodyColumns.SOURCE_MESSAGE_KEY + " text, " 5335fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank + BodyColumns.INTRO_TEXT + " text" 534a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank + ");"; 535a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank db.execSQL("create table " + Body.TABLE_NAME + s); 5369627d014e16235eadf981b9165807dc72a14a383Mihai Preda db.execSQL(createIndex(Body.TABLE_NAME, BodyColumns.MESSAGE_KEY)); 537a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 538a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 539a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank static void upgradeBodyTable(SQLiteDatabase db, int oldVersion, int newVersion) { 540657de3bfd6024811c6d6ef6fb2fb2c2750d9f54aMarc Blank if (oldVersion < 5) { 541e25698319325d5e9619bc45ae85d861b0f1c5954Marc Blank try { 542e25698319325d5e9619bc45ae85d861b0f1c5954Marc Blank db.execSQL("drop table " + Body.TABLE_NAME); 543e25698319325d5e9619bc45ae85d861b0f1c5954Marc Blank createBodyTable(db); 544e25698319325d5e9619bc45ae85d861b0f1c5954Marc Blank } catch (SQLException e) { 545e25698319325d5e9619bc45ae85d861b0f1c5954Marc Blank } 5465fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank } else if (oldVersion == 5) { 5475fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank try { 5485fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank db.execSQL("alter table " + Body.TABLE_NAME 5495fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank + " add " + BodyColumns.INTRO_TEXT + " text"); 5505fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank } catch (SQLException e) { 5515fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank // Shouldn't be needed unless we're debugging and interrupt the process 5525fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank Log.w(TAG, "Exception upgrading EmailProviderBody.db from v5 to v6", e); 5535fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank } 5545fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank oldVersion = 6; 555e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank } 556a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 557a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 558f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private SQLiteDatabase mDatabase; 559a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank private SQLiteDatabase mBodyDatabase; 560f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 56177398c42899a383680005b92955a29ab3d872c5cAndrew Stadler public synchronized SQLiteDatabase getDatabase(Context context) { 5620e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // Always return the cached database, if we've got one 5630e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank if (mDatabase != null) { 564f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler return mDatabase; 565a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 5660e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank 5670e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // Whenever we create or re-cache the databases, make sure that we haven't lost one 5680e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // to corruption 5690e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank checkDatabases(); 5700e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank 571f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler DatabaseHelper helper = new DatabaseHelper(context, DATABASE_NAME); 572f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler mDatabase = helper.getWritableDatabase(); 573a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank if (mDatabase != null) { 574f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler mDatabase.setLockingEnabled(true); 575a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank BodyDatabaseHelper bodyHelper = new BodyDatabaseHelper(context, BODY_DATABASE_NAME); 576a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank mBodyDatabase = bodyHelper.getWritableDatabase(); 577a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank if (mBodyDatabase != null) { 578a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank mBodyDatabase.setLockingEnabled(true); 579a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank String bodyFileName = mBodyDatabase.getPath(); 580a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank mDatabase.execSQL("attach \"" + bodyFileName + "\" as BodyDatabase"); 581a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank } 582a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 583ef83299b99288c00b9d661260d19715e73e6889cMarc Blank 584ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // Check for any orphaned Messages in the updated/deleted tables 585ef83299b99288c00b9d661260d19715e73e6889cMarc Blank deleteOrphans(mDatabase, Message.UPDATED_TABLE_NAME); 586ef83299b99288c00b9d661260d19715e73e6889cMarc Blank deleteOrphans(mDatabase, Message.DELETED_TABLE_NAME); 587ef83299b99288c00b9d661260d19715e73e6889cMarc Blank 588f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler return mDatabase; 589f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 590f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 591ef83299b99288c00b9d661260d19715e73e6889cMarc Blank /*package*/ static SQLiteDatabase getReadableDatabase(Context context) { 592ef83299b99288c00b9d661260d19715e73e6889cMarc Blank DatabaseHelper helper = new EmailProvider().new DatabaseHelper(context, DATABASE_NAME); 593ef83299b99288c00b9d661260d19715e73e6889cMarc Blank return helper.getReadableDatabase(); 594ef83299b99288c00b9d661260d19715e73e6889cMarc Blank } 595ef83299b99288c00b9d661260d19715e73e6889cMarc Blank 596ef83299b99288c00b9d661260d19715e73e6889cMarc Blank /*package*/ static void deleteOrphans(SQLiteDatabase database, String tableName) { 597ef83299b99288c00b9d661260d19715e73e6889cMarc Blank if (database != null) { 598ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // We'll look at all of the items in the table; there won't be many typically 599ef83299b99288c00b9d661260d19715e73e6889cMarc Blank Cursor c = database.query(tableName, ORPHANS_PROJECTION, null, null, null, null, null); 600ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // Usually, there will be nothing in these tables, so make a quick check 601ef83299b99288c00b9d661260d19715e73e6889cMarc Blank try { 602ef83299b99288c00b9d661260d19715e73e6889cMarc Blank if (c.getCount() == 0) return; 603ef83299b99288c00b9d661260d19715e73e6889cMarc Blank ArrayList<Long> foundMailboxes = new ArrayList<Long>(); 604ef83299b99288c00b9d661260d19715e73e6889cMarc Blank ArrayList<Long> notFoundMailboxes = new ArrayList<Long>(); 605ef83299b99288c00b9d661260d19715e73e6889cMarc Blank ArrayList<Long> deleteList = new ArrayList<Long>(); 606ef83299b99288c00b9d661260d19715e73e6889cMarc Blank String[] bindArray = new String[1]; 607ef83299b99288c00b9d661260d19715e73e6889cMarc Blank while (c.moveToNext()) { 608ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // Get the mailbox key and see if we've already found this mailbox 609ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // If so, we're fine 610ef83299b99288c00b9d661260d19715e73e6889cMarc Blank long mailboxId = c.getLong(ORPHANS_MAILBOX_KEY); 611ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // If we already know this mailbox doesn't exist, mark the message for deletion 612ef83299b99288c00b9d661260d19715e73e6889cMarc Blank if (notFoundMailboxes.contains(mailboxId)) { 613ef83299b99288c00b9d661260d19715e73e6889cMarc Blank deleteList.add(c.getLong(ORPHANS_ID)); 614ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // If we don't know about this mailbox, we'll try to find it 615ef83299b99288c00b9d661260d19715e73e6889cMarc Blank } else if (!foundMailboxes.contains(mailboxId)) { 616ef83299b99288c00b9d661260d19715e73e6889cMarc Blank bindArray[0] = Long.toString(mailboxId); 617ef83299b99288c00b9d661260d19715e73e6889cMarc Blank Cursor boxCursor = database.query(Mailbox.TABLE_NAME, 618ef83299b99288c00b9d661260d19715e73e6889cMarc Blank Mailbox.ID_PROJECTION, WHERE_ID, bindArray, null, null, null); 619ef83299b99288c00b9d661260d19715e73e6889cMarc Blank try { 620ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // If it exists, we'll add it to the "found" mailboxes 621ef83299b99288c00b9d661260d19715e73e6889cMarc Blank if (boxCursor.moveToFirst()) { 622ef83299b99288c00b9d661260d19715e73e6889cMarc Blank foundMailboxes.add(mailboxId); 623ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // Otherwise, we'll add to "not found" and mark the message for deletion 624ef83299b99288c00b9d661260d19715e73e6889cMarc Blank } else { 625ef83299b99288c00b9d661260d19715e73e6889cMarc Blank notFoundMailboxes.add(mailboxId); 626ef83299b99288c00b9d661260d19715e73e6889cMarc Blank deleteList.add(c.getLong(ORPHANS_ID)); 627ef83299b99288c00b9d661260d19715e73e6889cMarc Blank } 628ef83299b99288c00b9d661260d19715e73e6889cMarc Blank } finally { 629ef83299b99288c00b9d661260d19715e73e6889cMarc Blank boxCursor.close(); 630ef83299b99288c00b9d661260d19715e73e6889cMarc Blank } 631ef83299b99288c00b9d661260d19715e73e6889cMarc Blank } 632ef83299b99288c00b9d661260d19715e73e6889cMarc Blank } 633ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // Now, delete the orphan messages 634ef83299b99288c00b9d661260d19715e73e6889cMarc Blank for (long messageId: deleteList) { 635ef83299b99288c00b9d661260d19715e73e6889cMarc Blank bindArray[0] = Long.toString(messageId); 636ef83299b99288c00b9d661260d19715e73e6889cMarc Blank database.delete(tableName, WHERE_ID, bindArray); 637ef83299b99288c00b9d661260d19715e73e6889cMarc Blank } 638ef83299b99288c00b9d661260d19715e73e6889cMarc Blank } finally { 639ef83299b99288c00b9d661260d19715e73e6889cMarc Blank c.close(); 640ef83299b99288c00b9d661260d19715e73e6889cMarc Blank } 641ef83299b99288c00b9d661260d19715e73e6889cMarc Blank } 642ef83299b99288c00b9d661260d19715e73e6889cMarc Blank } 643ef83299b99288c00b9d661260d19715e73e6889cMarc Blank 644a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank private class BodyDatabaseHelper extends SQLiteOpenHelper { 645a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank BodyDatabaseHelper(Context context, String name) { 6460d00889f83fc8c1d69039a2c849b630fb4dd28ddAndrew Stadler super(context, name, null, BODY_DATABASE_VERSION); 647a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 648a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 649a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank @Override 650a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank public void onCreate(SQLiteDatabase db) { 6510e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank Log.d(TAG, "Creating EmailProviderBody database"); 652a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank createBodyTable(db); 653a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 654a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 655a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank @Override 656a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 657a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank upgradeBodyTable(db, oldVersion, newVersion); 658a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 659f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 660a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank @Override 661a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank public void onOpen(SQLiteDatabase db) { 662a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 663a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 664f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 665f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private class DatabaseHelper extends SQLiteOpenHelper { 666e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank Context mContext; 667e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank 668f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler DatabaseHelper(Context context, String name) { 6690d00889f83fc8c1d69039a2c849b630fb4dd28ddAndrew Stadler super(context, name, null, DATABASE_VERSION); 670e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank mContext = context; 671f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 672f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 673f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler @Override 674f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler public void onCreate(SQLiteDatabase db) { 6750e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank Log.d(TAG, "Creating EmailProvider database"); 676f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // Create all tables here; each class has its own method 677a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank createMessageTable(db); 678a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank createAttachmentTable(db); 679a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank createMailboxTable(db); 680a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank createHostAuthTable(db); 681a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank createAccountTable(db); 682f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank } 683f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 684f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler @Override 685f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 686657de3bfd6024811c6d6ef6fb2fb2c2750d9f54aMarc Blank // For versions prior to 5, delete all data 687657de3bfd6024811c6d6ef6fb2fb2c2750d9f54aMarc Blank // Versions >= 5 require that data be preserved! 688657de3bfd6024811c6d6ef6fb2fb2c2750d9f54aMarc Blank if (oldVersion < 5) { 689faed6178b1858f0e6df388a409d14fb3f94afefaMakoto Onuki android.accounts.Account[] accounts = AccountManager.get(mContext) 690faed6178b1858f0e6df388a409d14fb3f94afefaMakoto Onuki .getAccountsByType(Email.EXCHANGE_ACCOUNT_MANAGER_TYPE); 691e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank for (android.accounts.Account account: accounts) { 692e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank AccountManager.get(mContext).removeAccount(account, null, null); 693e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank } 694e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank resetMessageTable(db, oldVersion, newVersion); 695e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank resetAttachmentTable(db, oldVersion, newVersion); 696e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank resetMailboxTable(db, oldVersion, newVersion); 697e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank resetHostAuthTable(db, oldVersion, newVersion); 698e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank resetAccountTable(db, oldVersion, newVersion); 6990d00889f83fc8c1d69039a2c849b630fb4dd28ddAndrew Stadler return; 7000d00889f83fc8c1d69039a2c849b630fb4dd28ddAndrew Stadler } 7010d00889f83fc8c1d69039a2c849b630fb4dd28ddAndrew Stadler if (oldVersion == 5) { 7020d00889f83fc8c1d69039a2c849b630fb4dd28ddAndrew Stadler // Message Tables: Add SyncColumns.SERVER_TIMESTAMP 7035fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank try { 7045fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank db.execSQL("alter table " + Message.TABLE_NAME 7055fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank + " add column " + SyncColumns.SERVER_TIMESTAMP + " integer" + ";"); 7065fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank db.execSQL("alter table " + Message.UPDATED_TABLE_NAME 7075fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank + " add column " + SyncColumns.SERVER_TIMESTAMP + " integer" + ";"); 7085fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank db.execSQL("alter table " + Message.DELETED_TABLE_NAME 7095fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank + " add column " + SyncColumns.SERVER_TIMESTAMP + " integer" + ";"); 7105fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank } catch (SQLException e) { 7115fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank // Shouldn't be needed unless we're debugging and interrupt the process 7125fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank Log.w(TAG, "Exception upgrading EmailProvider.db from v5 to v6", e); 7135fc57eccefeba517fe5e6f093786f37c6c4d50e6Marc Blank } 7140d00889f83fc8c1d69039a2c849b630fb4dd28ddAndrew Stadler oldVersion = 6; 715e7e1ca432e1aace5b7f11a3f1684a4abc503e6b2Marc Blank } 716ef83299b99288c00b9d661260d19715e73e6889cMarc Blank if (oldVersion == 6) { 717ef83299b99288c00b9d661260d19715e73e6889cMarc Blank // Use the newer mailbox_delete trigger 718367963639d4291511b7e175a208e2b553aac26c2Marc Blank db.execSQL("drop trigger mailbox_delete;"); 719ef83299b99288c00b9d661260d19715e73e6889cMarc Blank db.execSQL(TRIGGER_MAILBOX_DELETE); 720ef83299b99288c00b9d661260d19715e73e6889cMarc Blank oldVersion = 7; 721ef83299b99288c00b9d661260d19715e73e6889cMarc Blank } 722fc8d943a828cd79ff71c703ced37001bd5482173Andrew Stadler if (oldVersion == 7) { 723fc8d943a828cd79ff71c703ced37001bd5482173Andrew Stadler // add the security (provisioning) column 724fc8d943a828cd79ff71c703ced37001bd5482173Andrew Stadler try { 725fc8d943a828cd79ff71c703ced37001bd5482173Andrew Stadler db.execSQL("alter table " + Account.TABLE_NAME 726fc8d943a828cd79ff71c703ced37001bd5482173Andrew Stadler + " add column " + AccountColumns.SECURITY_FLAGS + " integer" + ";"); 727fc8d943a828cd79ff71c703ced37001bd5482173Andrew Stadler } catch (SQLException e) { 728fc8d943a828cd79ff71c703ced37001bd5482173Andrew Stadler // Shouldn't be needed unless we're debugging and interrupt the process 729fc8d943a828cd79ff71c703ced37001bd5482173Andrew Stadler Log.w(TAG, "Exception upgrading EmailProvider.db from 7 to 8 " + e); 730fc8d943a828cd79ff71c703ced37001bd5482173Andrew Stadler } 731fc8d943a828cd79ff71c703ced37001bd5482173Andrew Stadler oldVersion = 8; 732fc8d943a828cd79ff71c703ced37001bd5482173Andrew Stadler } 733345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler if (oldVersion == 8) { 734345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler // accounts: add security sync key & user signature columns 735345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler try { 736345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler db.execSQL("alter table " + Account.TABLE_NAME 737345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler + " add column " + AccountColumns.SECURITY_SYNC_KEY + " text" + ";"); 738345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler db.execSQL("alter table " + Account.TABLE_NAME 739345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler + " add column " + AccountColumns.SIGNATURE + " text" + ";"); 740345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler } catch (SQLException e) { 741345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler // Shouldn't be needed unless we're debugging and interrupt the process 742345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler Log.w(TAG, "Exception upgrading EmailProvider.db from 8 to 9 " + e); 743345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler } 744345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler oldVersion = 9; 745345fb8b737c1632fb2a7e69ac44b8612be6237edAndrew Stadler } 7464006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank if (oldVersion == 9) { 7474006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank // Message: add meeting info column into Message tables 7484006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank try { 7494006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank db.execSQL("alter table " + Message.TABLE_NAME 7504006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank + " add column " + MessageColumns.MEETING_INFO + " text" + ";"); 7514006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank db.execSQL("alter table " + Message.UPDATED_TABLE_NAME 7524006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank + " add column " + MessageColumns.MEETING_INFO + " text" + ";"); 7534006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank db.execSQL("alter table " + Message.DELETED_TABLE_NAME 7544006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank + " add column " + MessageColumns.MEETING_INFO + " text" + ";"); 7554006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank } catch (SQLException e) { 7564006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank // Shouldn't be needed unless we're debugging and interrupt the process 7574006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank Log.w(TAG, "Exception upgrading EmailProvider.db from 9 to 10 " + e); 7584006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank } 7594006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank oldVersion = 10; 7604006e5fc224d097450fd66a321901b6636f7d9c4Marc Blank } 7613aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler if (oldVersion == 10) { 7623aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler // Attachment: add content and flags columns 7633aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler try { 7643aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler db.execSQL("alter table " + Attachment.TABLE_NAME 7653aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler + " add column " + AttachmentColumns.CONTENT + " text" + ";"); 7663aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler db.execSQL("alter table " + Attachment.TABLE_NAME 7673aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler + " add column " + AttachmentColumns.FLAGS + " integer" + ";"); 7683aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler } catch (SQLException e) { 7693aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler // Shouldn't be needed unless we're debugging and interrupt the process 7703aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler Log.w(TAG, "Exception upgrading EmailProvider.db from 10 to 11 " + e); 7713aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler } 7723aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler oldVersion = 11; 7733aaba9eb87db34ea0861d70d5c08f84d7ca97ab0Andrew Stadler } 77420225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki if (oldVersion == 11) { 77520225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki // Attachment: add content_bytes 77620225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki try { 77720225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki db.execSQL("alter table " + Attachment.TABLE_NAME 77820225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki + " add column " + AttachmentColumns.CONTENT_BYTES + " blob" + ";"); 77920225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki } catch (SQLException e) { 78020225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki // Shouldn't be needed unless we're debugging and interrupt the process 78120225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki Log.w(TAG, "Exception upgrading EmailProvider.db from 11 to 12 " + e); 78220225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki } 78320225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki oldVersion = 12; 78420225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki } 785f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 786f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 787f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler @Override 788f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler public void onOpen(SQLiteDatabase db) { 789f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 790f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 791f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 792f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler @Override 793f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler public int delete(Uri uri, String selection, String[] selectionArgs) { 794fb7974f5bfb6275fb856b0f7ff386ef10680c83aMihai Preda final int match = sURIMatcher.match(uri); 795a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank Context context = getContext(); 796cba3a48f97ae2e6d875ac4284a4066da94c922d5Marc Blank // Pick the correct database for this operation 797cba3a48f97ae2e6d875ac4284a4066da94c922d5Marc Blank // If we're in a transaction already (which would happen during applyBatch), then the 798cba3a48f97ae2e6d875ac4284a4066da94c922d5Marc Blank // body database is already attached to the email database and any attempt to use the 799cba3a48f97ae2e6d875ac4284a4066da94c922d5Marc Blank // body database directly will result in a SQLiteException (the database is locked) 800a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank SQLiteDatabase db = getDatabase(context); 801f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler int table = match >> BASE_SHIFT; 8022c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank String id = "0"; 803cba3a48f97ae2e6d875ac4284a4066da94c922d5Marc Blank boolean messageDeletion = false; 804f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 805f33986d5cc248d2eeed0707143d81e94866f8e3aMihai Preda if (Email.LOGD) { 806f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler Log.v(TAG, "EmailProvider.delete: uri=" + uri + ", match is " + match); 807fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank } 808f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 809b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank int result = -1; 810f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 8112c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank try { 8122c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank switch (match) { 8132c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank // These are cases in which one or more Messages might get deleted, either by 8142c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank // cascade or explicitly 8152c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case MAILBOX_ID: 8162c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case MAILBOX: 8172c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case ACCOUNT_ID: 8182c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case ACCOUNT: 8192c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case MESSAGE: 820f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank case SYNCED_MESSAGE_ID: 8212c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case MESSAGE_ID: 8222c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank // Handle lost Body records here, since this cannot be done in a trigger 8232c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank // The process is: 824a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank // 1) Begin a transaction, ensuring that both databases are affected atomically 825a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank // 2) Do the requested deletion, with cascading deletions handled in triggers 826a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank // 3) End the transaction, committing all changes atomically 8276c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler // 8286c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler // Bodies are auto-deleted here; Attachments are auto-deleted via trigger 829a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank 830cba3a48f97ae2e6d875ac4284a4066da94c922d5Marc Blank messageDeletion = true; 8318587aa61211d288d05b5fb2ddf02d69cabe6a9e2Marc Blank db.beginTransaction(); 8322c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank break; 8332c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank } 8342c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank switch (match) { 8352c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case BODY_ID: 836f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank case DELETED_MESSAGE_ID: 837f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank case SYNCED_MESSAGE_ID: 8382c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case MESSAGE_ID: 8392c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case UPDATED_MESSAGE_ID: 8402c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case ATTACHMENT_ID: 8412c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case MAILBOX_ID: 8422c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case ACCOUNT_ID: 8432c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case HOSTAUTH_ID: 8442c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank id = uri.getPathSegments().get(1); 845f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank if (match == SYNCED_MESSAGE_ID) { 846f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank // For synced messages, first copy the old message to the deleted table and 847f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank // delete it from the updated table (in case it was updated first) 848f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank // Note that this is all within a transaction, for atomicity 849f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank db.execSQL(DELETED_MESSAGE_INSERT + id); 850f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank db.execSQL(UPDATED_MESSAGE_DELETE + id); 851f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank } 8522c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank result = db.delete(TABLE_NAMES[table], whereWithId(id, selection), 8532c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank selectionArgs); 8542c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank break; 8556c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler case ATTACHMENTS_MESSAGE_ID: 8566c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler // All attachments for the given message 8576c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler id = uri.getPathSegments().get(2); 8586c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler result = db.delete(TABLE_NAMES[table], 8596c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler whereWith(Attachment.MESSAGE_KEY + "=" + id, selection), selectionArgs); 8606c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler break; 8616c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler 8622c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case BODY: 8632c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case MESSAGE: 864f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank case DELETED_MESSAGE: 8652c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case UPDATED_MESSAGE: 8662c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case ATTACHMENT: 8672c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case MAILBOX: 8682c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case ACCOUNT: 8692c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank case HOSTAUTH: 8702c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank result = db.delete(TABLE_NAMES[table], selection, selectionArgs); 8712c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank break; 8726c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler 8732c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank default: 8742c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank throw new IllegalArgumentException("Unknown URI " + uri); 8752c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank } 876cba3a48f97ae2e6d875ac4284a4066da94c922d5Marc Blank if (messageDeletion) { 877fb7974f5bfb6275fb856b0f7ff386ef10680c83aMihai Preda if (match == MESSAGE_ID) { 8785f4dbd64389cd6540a93cde1daed304bf9392a01Andrew Stadler // Delete the Body record associated with the deleted message 879f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank db.execSQL(DELETE_BODY + id); 880fb7974f5bfb6275fb856b0f7ff386ef10680c83aMihai Preda } else { 881fb7974f5bfb6275fb856b0f7ff386ef10680c83aMihai Preda // Delete any orphaned Body records 882fb7974f5bfb6275fb856b0f7ff386ef10680c83aMihai Preda db.execSQL(DELETE_ORPHAN_BODIES); 883cba3a48f97ae2e6d875ac4284a4066da94c922d5Marc Blank } 8848587aa61211d288d05b5fb2ddf02d69cabe6a9e2Marc Blank db.setTransactionSuccessful(); 8855f4dbd64389cd6540a93cde1daed304bf9392a01Andrew Stadler } 8860e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } catch (SQLiteException e) { 8870e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank checkDatabases(); 8880e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank throw e; 8892c67f1f8b869454ed24c0ac3c813aca26d2f3978Marc Blank } finally { 890cba3a48f97ae2e6d875ac4284a4066da94c922d5Marc Blank if (messageDeletion) { 8918587aa61211d288d05b5fb2ddf02d69cabe6a9e2Marc Blank db.endTransaction(); 8925f4dbd64389cd6540a93cde1daed304bf9392a01Andrew Stadler } 893f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 894626f3e48a4f14c38a973dd2bea2e2debea7637a5Andrew Stadler getContext().getContentResolver().notifyChange(uri, null); 895626f3e48a4f14c38a973dd2bea2e2debea7637a5Andrew Stadler return result; 896f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 897f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 898f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler @Override 899f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler // Use the email- prefix because message, mailbox, and account are so generic (e.g. SMS, IM) 900f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler public String getType(Uri uri) { 901f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler int match = sURIMatcher.match(uri); 902f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler switch (match) { 903a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank case BODY_ID: 904a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank return "vnd.android.cursor.item/email-body"; 905a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank case BODY: 906fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank return "vnd.android.cursor.dir/email-message"; 907e34525d0f026a7467cee1cb5fddcf25ba6f35207Marc Blank case UPDATED_MESSAGE_ID: 908a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank case MESSAGE_ID: 909a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank return "vnd.android.cursor.item/email-message"; 910fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank case MAILBOX_MESSAGES: 911e34525d0f026a7467cee1cb5fddcf25ba6f35207Marc Blank case UPDATED_MESSAGE: 912fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank case MESSAGE: 913a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank return "vnd.android.cursor.dir/email-message"; 914fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank case ACCOUNT_MAILBOXES: 915fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank case MAILBOX: 916fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank return "vnd.android.cursor.dir/email-mailbox"; 917fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank case MAILBOX_ID: 918fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank return "vnd.android.cursor.item/email-mailbox"; 919fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank case ACCOUNT: 920fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank return "vnd.android.cursor.dir/email-account"; 921fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank case ACCOUNT_ID: 922fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank return "vnd.android.cursor.item/email-account"; 9234119218e2fd64341ac946fb8f2cbdb796a444cb8Andrew Stadler case ATTACHMENTS_MESSAGE_ID: 924fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank case ATTACHMENT: 925fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank return "vnd.android.cursor.dir/email-attachment"; 926fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank case ATTACHMENT_ID: 927fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank return "vnd.android.cursor.item/email-attachment"; 928fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank case HOSTAUTH: 929fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank return "vnd.android.cursor.dir/email-hostauth"; 930fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank case HOSTAUTH_ID: 931fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank return "vnd.android.cursor.item/email-hostauth"; 932fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank default: 933fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank throw new IllegalArgumentException("Unknown URI " + uri); 934f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 935f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 936f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 937f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler @Override 938f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler public Uri insert(Uri uri, ContentValues values) { 939f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler int match = sURIMatcher.match(uri); 940a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank Context context = getContext(); 941cba3a48f97ae2e6d875ac4284a4066da94c922d5Marc Blank // See the comment at delete(), above 942a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank SQLiteDatabase db = getDatabase(context); 943f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler int table = match >> BASE_SHIFT; 944a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank long id; 945f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 946f33986d5cc248d2eeed0707143d81e94866f8e3aMihai Preda if (Email.LOGD) { 947f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler Log.v(TAG, "EmailProvider.insert: uri=" + uri + ", match is " + match); 948fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank } 949f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 950626f3e48a4f14c38a973dd2bea2e2debea7637a5Andrew Stadler Uri resultUri = null; 951f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 9520e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank try { 9530e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank switch (match) { 9540e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case UPDATED_MESSAGE: 9550e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case DELETED_MESSAGE: 9560e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case BODY: 9570e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case MESSAGE: 9580e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case ATTACHMENT: 9590e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case MAILBOX: 9600e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case ACCOUNT: 9610e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case HOSTAUTH: 9620e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank id = db.insert(TABLE_NAMES[table], "foo", values); 9630e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank resultUri = ContentUris.withAppendedId(uri, id); 9640e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // Clients shouldn't normally be adding rows to these tables, as they are 9650e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // maintained by triggers. However, we need to be able to do this for unit 9660e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // testing, so we allow the insert and then throw the same exception that we 9670e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // would if this weren't allowed. 9680e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank if (match == UPDATED_MESSAGE || match == DELETED_MESSAGE) { 9690e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank throw new IllegalArgumentException("Unknown URL " + uri); 9700e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } 9710e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank break; 9720e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case MAILBOX_ID: 9730e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // This implies adding a message to a mailbox 9740e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // Hmm, a problem here is that we can't link the account as well, so it must be 9750e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // already in the values... 9760e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank id = Long.parseLong(uri.getPathSegments().get(1)); 9770e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank values.put(MessageColumns.MAILBOX_KEY, id); 9780e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank resultUri = insert(Message.CONTENT_URI, values); 9790e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank break; 9800e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case MESSAGE_ID: 9810e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // This implies adding an attachment to a message. 9820e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank id = Long.parseLong(uri.getPathSegments().get(1)); 9830e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank values.put(AttachmentColumns.MESSAGE_KEY, id); 9840e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank resultUri = insert(Attachment.CONTENT_URI, values); 9850e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank break; 9860e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case ACCOUNT_ID: 9870e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // This implies adding a mailbox to an account. 9880e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank id = Long.parseLong(uri.getPathSegments().get(1)); 9890e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank values.put(MailboxColumns.ACCOUNT_KEY, id); 9900e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank resultUri = insert(Mailbox.CONTENT_URI, values); 9910e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank break; 9920e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case ATTACHMENTS_MESSAGE_ID: 9930e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank id = db.insert(TABLE_NAMES[table], "foo", values); 9940e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank resultUri = ContentUris.withAppendedId(Attachment.CONTENT_URI, id); 9950e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank break; 9960e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank default: 997ef83299b99288c00b9d661260d19715e73e6889cMarc Blank throw new IllegalArgumentException("Unknown URL " + uri); 9980e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } 9990e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } catch (SQLiteException e) { 10000e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank checkDatabases(); 10010e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank throw e; 1002f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 1003f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 1004a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank // Notify with the base uri, not the new uri (nobody is watching a new record) 1005a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank getContext().getContentResolver().notifyChange(uri, null); 1006626f3e48a4f14c38a973dd2bea2e2debea7637a5Andrew Stadler return resultUri; 1007f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 1008f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 1009f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler @Override 1010f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler public boolean onCreate() { 10110e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank checkDatabases(); 1012f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler return false; 1013f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 1014f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 10150e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank /** 10160e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank * The idea here is that the two databases (EmailProvider.db and EmailProviderBody.db must 10170e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank * always be in sync (i.e. there are two database or NO databases). This code will delete 10180e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank * any "orphan" database, so that both will be created together. Note that an "orphan" database 10190e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank * will exist after either of the individual databases is deleted due to data corruption. 10200e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank */ 10210e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank public void checkDatabases() { 10220e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // Uncache the databases 10230e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank if (mDatabase != null) { 10240e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank mDatabase = null; 10250e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } 10260e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank if (mBodyDatabase != null) { 10270e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank mBodyDatabase = null; 10280e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } 10290e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // Look for orphans, and delete as necessary; these must always be in sync 10300e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank File databaseFile = getContext().getDatabasePath(DATABASE_NAME); 10310e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank File bodyFile = getContext().getDatabasePath(BODY_DATABASE_NAME); 10320e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank 10330e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // TODO Make sure attachments are deleted 10340e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank if (databaseFile.exists() && !bodyFile.exists()) { 10350e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank Log.w(TAG, "Deleting orphaned EmailProvider database..."); 10360e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank databaseFile.delete(); 10370e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } else if (bodyFile.exists() && !databaseFile.exists()) { 10380e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank Log.w(TAG, "Deleting orphaned EmailProviderBody database..."); 10390e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank bodyFile.delete(); 10400e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } 10410e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } 10420e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank 1043f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler @Override 1044758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 1045fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank String sortOrder) { 1046f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler Cursor c = null; 1047a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank Uri notificationUri = EmailContent.CONTENT_URI; 1048f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler int match = sURIMatcher.match(uri); 1049a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank Context context = getContext(); 1050cba3a48f97ae2e6d875ac4284a4066da94c922d5Marc Blank // See the comment at delete(), above 1051a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank SQLiteDatabase db = getDatabase(context); 1052f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler int table = match >> BASE_SHIFT; 1053f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler String id; 1054f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 1055f33986d5cc248d2eeed0707143d81e94866f8e3aMihai Preda if (Email.LOGD) { 1056f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler Log.v(TAG, "EmailProvider.query: uri=" + uri + ", match is " + match); 1057fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank } 1058f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 10590e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank try { 10600e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank switch (match) { 10610e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case BODY: 10620e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case MESSAGE: 10630e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case UPDATED_MESSAGE: 10640e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case DELETED_MESSAGE: 10650e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case ATTACHMENT: 10660e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case MAILBOX: 10670e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case ACCOUNT: 10680e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case HOSTAUTH: 10690e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank c = db.query(TABLE_NAMES[table], projection, 10700e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank selection, selectionArgs, null, null, sortOrder); 10710e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank break; 10720e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case BODY_ID: 10730e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case MESSAGE_ID: 10740e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case DELETED_MESSAGE_ID: 10750e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case UPDATED_MESSAGE_ID: 10760e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case ATTACHMENT_ID: 10770e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case MAILBOX_ID: 10780e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case ACCOUNT_ID: 10790e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case HOSTAUTH_ID: 10800e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank id = uri.getPathSegments().get(1); 10810e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank c = db.query(TABLE_NAMES[table], projection, 10820e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank whereWithId(id, selection), selectionArgs, null, null, sortOrder); 10830e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank break; 10840e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case ATTACHMENTS_MESSAGE_ID: 10850e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // All attachments for the given message 10860e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank id = uri.getPathSegments().get(2); 10870e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank c = db.query(Attachment.TABLE_NAME, projection, 10880e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank whereWith(Attachment.MESSAGE_KEY + "=" + id, selection), 10890e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank selectionArgs, null, null, sortOrder); 10900e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank break; 10910e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank default: 10920e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank throw new IllegalArgumentException("Unknown URI " + uri); 10930e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } 10940e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } catch (SQLiteException e) { 10950e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank checkDatabases(); 10960e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank throw e; 1097f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 1098f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 1099f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler if ((c != null) && !isTemporary()) { 1100f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler c.setNotificationUri(getContext().getContentResolver(), notificationUri); 1101f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 1102f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler return c; 1103f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 1104f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler 1105f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private String whereWithId(String id, String selection) { 1106f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler StringBuilder sb = new StringBuilder(256); 1107f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler sb.append("_id="); 1108f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler sb.append(id); 1109f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler if (selection != null) { 11106c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler sb.append(" AND ("); 1111f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler sb.append(selection); 11126c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler sb.append(')'); 1113f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 1114f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler return sb.toString(); 1115f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 1116f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 11176c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler /** 11186c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler * Combine a locally-generated selection with a user-provided selection 11196c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler * 11206c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler * This introduces risk that the local selection might insert incorrect chars 11216c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler * into the SQL, so use caution. 11226c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler * 11236c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler * @param where locally-generated selection, must not be null 11246c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler * @param selection user-provided selection, may be null 11256c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler * @return a single selection string 11266c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler */ 1127f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler private String whereWith(String where, String selection) { 11286c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler if (selection == null) { 11296c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler return where; 1130f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 11316c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler StringBuilder sb = new StringBuilder(where); 11326c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler sb.append(" AND ("); 11336c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler sb.append(selection); 11346c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler sb.append(')'); 11356c21942ec45f561d711b3d74ecca8e62afb735c4Andrew Stadler 1136f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler return sb.toString(); 1137f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 1138f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 1139f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler @Override 1140f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1141f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler int match = sURIMatcher.match(uri); 1142a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank Context context = getContext(); 1143cba3a48f97ae2e6d875ac4284a4066da94c922d5Marc Blank // See the comment at delete(), above 1144a867ebba6233becf2061c80e1c53d7d395a6cffcMarc Blank SQLiteDatabase db = getDatabase(context); 1145f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler int table = match >> BASE_SHIFT; 1146626f3e48a4f14c38a973dd2bea2e2debea7637a5Andrew Stadler int result; 1147a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 1148f33986d5cc248d2eeed0707143d81e94866f8e3aMihai Preda if (Email.LOGD) { 1149f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank Log.v(TAG, "EmailProvider.update: uri=" + uri + ", match is " + match); 1150a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank } 1151a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 1152758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank // We do NOT allow setting of unreadCount via the provider 1153758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank // This column is maintained via triggers 1154758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank if (match == MAILBOX_ID || match == MAILBOX) { 1155758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank values.remove(MailboxColumns.UNREAD_COUNT); 1156758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank } 1157758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank 11580e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // Handle this special case the fastest possible way 11590e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank if (uri == INTEGRITY_CHECK_URI) { 11600e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank checkDatabases(); 11610e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank return 0; 11620e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } 11630e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank 1164c0c9c33322deecace00a32766e0a1b355aad4b31Marc Blank String id; 11650e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank try { 11660e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank switch (match) { 11670e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case MAILBOX_ID_ADD_TO_FIELD: 11680e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case ACCOUNT_ID_ADD_TO_FIELD: 11690e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank db.beginTransaction(); 11700e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank id = uri.getPathSegments().get(1); 11710e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank String field = values.getAsString(EmailContent.FIELD_COLUMN_NAME); 11720e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank Long add = values.getAsLong(EmailContent.ADD_COLUMN_NAME); 11730e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank if (field == null || add == null) { 11740e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank throw new IllegalArgumentException("No field/add specified " + uri); 1175c0c9c33322deecace00a32766e0a1b355aad4b31Marc Blank } 11760e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank Cursor c = db.query(TABLE_NAMES[table], 11770e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank new String[] {EmailContent.RECORD_ID, field}, 11780e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank whereWithId(id, selection), 11790e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank selectionArgs, null, null, null); 11800e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank try { 11810e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank result = 0; 11820e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank ContentValues cv = new ContentValues(); 11830e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank String[] bind = new String[1]; 11840e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank while (c.moveToNext()) { 11850e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank bind[0] = c.getString(0); 11860e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank long value = c.getLong(1) + add; 11870e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank cv.put(field, value); 11880e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank result = db.update(TABLE_NAMES[table], cv, ID_EQUALS, bind); 11890e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } 11900e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } finally { 11910e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank c.close(); 11920e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } 11930e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank db.setTransactionSuccessful(); 11940e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank db.endTransaction(); 11950e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank break; 11960e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case BODY_ID: 11970e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case MESSAGE_ID: 11980e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case SYNCED_MESSAGE_ID: 11990e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case UPDATED_MESSAGE_ID: 12000e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case ATTACHMENT_ID: 12010e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case MAILBOX_ID: 12020e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case ACCOUNT_ID: 12030e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case HOSTAUTH_ID: 12040e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank id = uri.getPathSegments().get(1); 12050e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank if (match == SYNCED_MESSAGE_ID) { 12060e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // For synced messages, first copy the old message to the updated table 12070e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // Note the insert or ignore semantics, guaranteeing that only the first 12080e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // update will be reflected in the updated message table; therefore this row 12090e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank // will always have the "original" data 12100e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank db.execSQL(UPDATED_MESSAGE_INSERT + id); 12110e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } else if (match == MESSAGE_ID) { 12120e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank db.execSQL(UPDATED_MESSAGE_DELETE + id); 12130e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } 12140e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank result = db.update(TABLE_NAMES[table], values, whereWithId(id, selection), 12150e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank selectionArgs); 12160e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank break; 12170e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case BODY: 12180e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case MESSAGE: 12190e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case UPDATED_MESSAGE: 12200e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case ATTACHMENT: 12210e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case MAILBOX: 12220e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case ACCOUNT: 12230e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank case HOSTAUTH: 12240e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank result = db.update(TABLE_NAMES[table], values, selection, selectionArgs); 12250e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank break; 12260e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank default: 12270e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank throw new IllegalArgumentException("Unknown URI " + uri); 12280e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } 12290e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank } catch (SQLiteException e) { 12300e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank checkDatabases(); 12310e1595c177e40428b267a8696dfc05d015ce6a2fMarc Blank throw e; 1232fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank } 1233a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank 1234626f3e48a4f14c38a973dd2bea2e2debea7637a5Andrew Stadler getContext().getContentResolver().notifyChange(uri, null); 1235626f3e48a4f14c38a973dd2bea2e2debea7637a5Andrew Stadler return result; 1236fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank } 1237f374304e92cc6c27ce1a59242d4b9ff02a9cbb14Marc Blank 1238fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank /* (non-Javadoc) 123984969fb580f569c0e3625a3c59a71d2909ae198dFred Quintana * @see android.content.ContentProvider#applyBatch(android.content.ContentProviderOperation) 1240fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank */ 1241758a532fce2f672673d38b2daa5f67eb757b118bMarc Blank @Override 124284969fb580f569c0e3625a3c59a71d2909ae198dFred Quintana public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 1243b6493a07ef625c0e290890c2e60256b47a066e5eMarc Blank throws OperationApplicationException { 1244cba3a48f97ae2e6d875ac4284a4066da94c922d5Marc Blank Context context = getContext(); 1245cba3a48f97ae2e6d875ac4284a4066da94c922d5Marc Blank SQLiteDatabase db = getDatabase(context); 1246fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank db.beginTransaction(); 1247fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank try { 1248fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank ContentProviderResult[] results = super.applyBatch(operations); 1249fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank db.setTransactionSuccessful(); 1250fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank return results; 1251fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank } finally { 1252fae4727a911a13cd0bfaaf2f1167d780bafb592bMarc Blank db.endTransaction(); 1253f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 1254f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler } 1255f3d5b202360031979714c3e366c386bcc7e6a40eAndrew Stadler} 1256