DBHelper.java revision 21b2522d7f6b2bce8fc3382e6e532d4b4df1b140
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.email.provider;
18
19import android.accounts.AccountManager;
20import android.content.ContentResolver;
21import android.content.ContentValues;
22import android.content.Context;
23import android.database.Cursor;
24import android.database.SQLException;
25import android.database.sqlite.SQLiteDatabase;
26import android.database.sqlite.SQLiteOpenHelper;
27import android.provider.CalendarContract;
28import android.provider.ContactsContract;
29import android.text.TextUtils;
30
31import com.android.email.R;
32import com.android.email2.ui.MailActivityEmail;
33import com.android.emailcommon.mail.Address;
34import com.android.emailcommon.provider.Account;
35import com.android.emailcommon.provider.EmailContent;
36import com.android.emailcommon.provider.EmailContent.AccountColumns;
37import com.android.emailcommon.provider.EmailContent.Attachment;
38import com.android.emailcommon.provider.EmailContent.AttachmentColumns;
39import com.android.emailcommon.provider.EmailContent.Body;
40import com.android.emailcommon.provider.EmailContent.BodyColumns;
41import com.android.emailcommon.provider.EmailContent.HostAuthColumns;
42import com.android.emailcommon.provider.EmailContent.MailboxColumns;
43import com.android.emailcommon.provider.EmailContent.Message;
44import com.android.emailcommon.provider.EmailContent.MessageColumns;
45import com.android.emailcommon.provider.EmailContent.PolicyColumns;
46import com.android.emailcommon.provider.EmailContent.QuickResponseColumns;
47import com.android.emailcommon.provider.EmailContent.SyncColumns;
48import com.android.emailcommon.provider.HostAuth;
49import com.android.emailcommon.provider.Mailbox;
50import com.android.emailcommon.provider.Policy;
51import com.android.emailcommon.provider.QuickResponse;
52import com.android.emailcommon.service.LegacyPolicySet;
53import com.android.emailcommon.service.SyncWindow;
54import com.android.mail.providers.UIProvider;
55import com.android.mail.utils.LogUtils;
56import com.google.common.annotations.VisibleForTesting;
57import com.google.common.collect.ImmutableMap;
58
59import java.util.Map;
60
61public final class DBHelper {
62    private static final String TAG = "EmailProvider";
63
64    private static final String LEGACY_SCHEME_IMAP = "imap";
65    private static final String LEGACY_SCHEME_POP3 = "pop3";
66    private static final String LEGACY_SCHEME_EAS = "eas";
67
68    private static final String WHERE_ID = EmailContent.RECORD_ID + "=?";
69
70    private static final String TRIGGER_MAILBOX_DELETE =
71        "create trigger mailbox_delete before delete on " + Mailbox.TABLE_NAME +
72        " begin" +
73        " delete from " + Message.TABLE_NAME +
74        "  where " + MessageColumns.MAILBOX_KEY + "=old." + EmailContent.RECORD_ID +
75        "; delete from " + Message.UPDATED_TABLE_NAME +
76        "  where " + MessageColumns.MAILBOX_KEY + "=old." + EmailContent.RECORD_ID +
77        "; delete from " + Message.DELETED_TABLE_NAME +
78        "  where " + MessageColumns.MAILBOX_KEY + "=old." + EmailContent.RECORD_ID +
79        "; end";
80
81    private static final String TRIGGER_ACCOUNT_DELETE =
82        "create trigger account_delete before delete on " + Account.TABLE_NAME +
83        " begin delete from " + Mailbox.TABLE_NAME +
84        " where " + MailboxColumns.ACCOUNT_KEY + "=old." + EmailContent.RECORD_ID +
85        "; delete from " + HostAuth.TABLE_NAME +
86        " where " + EmailContent.RECORD_ID + "=old." + AccountColumns.HOST_AUTH_KEY_RECV +
87        "; delete from " + HostAuth.TABLE_NAME +
88        " where " + EmailContent.RECORD_ID + "=old." + AccountColumns.HOST_AUTH_KEY_SEND +
89        "; delete from " + Policy.TABLE_NAME +
90        " where " + EmailContent.RECORD_ID + "=old." + AccountColumns.POLICY_KEY +
91        "; end";
92
93    // Any changes to the database format *must* include update-in-place code.
94    // Original version: 3
95    // Version 4: Database wipe required; changing AccountManager interface w/Exchange
96    // Version 5: Database wipe required; changing AccountManager interface w/Exchange
97    // Version 6: Adding Message.mServerTimeStamp column
98    // Version 7: Replace the mailbox_delete trigger with a version that removes orphaned messages
99    //            from the Message_Deletes and Message_Updates tables
100    // Version 8: Add security flags column to accounts table
101    // Version 9: Add security sync key and signature to accounts table
102    // Version 10: Add meeting info to message table
103    // Version 11: Add content and flags to attachment table
104    // Version 12: Add content_bytes to attachment table. content is deprecated.
105    // Version 13: Add messageCount to Mailbox table.
106    // Version 14: Add snippet to Message table
107    // Version 15: Fix upgrade problem in version 14.
108    // Version 16: Add accountKey to Attachment table
109    // Version 17: Add parentKey to Mailbox table
110    // Version 18: Copy Mailbox.displayName to Mailbox.serverId for all IMAP & POP3 mailboxes.
111    //             Column Mailbox.serverId is used for the server-side pathname of a mailbox.
112    // Version 19: Add Policy table; add policyKey to Account table and trigger to delete an
113    //             Account's policy when the Account is deleted
114    // Version 20: Add new policies to Policy table
115    // Version 21: Add lastSeenMessageKey column to Mailbox table
116    // Version 22: Upgrade path for IMAP/POP accounts to integrate with AccountManager
117    // Version 23: Add column to mailbox table for time of last access
118    // Version 24: Add column to hostauth table for client cert alias
119    // Version 25: Added QuickResponse table
120    // Version 26: Update IMAP accounts to add FLAG_SUPPORTS_SEARCH flag
121    // Version 27: Add protocolSearchInfo to Message table
122    // Version 28: Add notifiedMessageId and notifiedMessageCount to Account
123    // Version 29: Add protocolPoliciesEnforced and protocolPoliciesUnsupported to Policy
124    // Version 30: Use CSV of RFC822 addresses instead of "packed" values
125    // Version 31: Add columns to mailbox for ui status/last result
126    // Version 32: Add columns to mailbox for last notified message key/count; insure not null
127    //             for "notified" columns
128    // Version 33: Add columns to attachment for ui provider columns
129    // Version 34: Add total count to mailbox
130    // Version 35: Set up defaults for lastTouchedCount for drafts and sent
131    // Version 36: mblank intentionally left this space
132    // Version 37: Add flag for settings support in folders
133    // Version 38&39: Add threadTopic to message (for future support)
134    // Version 39 is last Email1 version
135    // Version 100 is first Email2 version
136    // Version 101 SHOULD NOT BE USED
137    // Version 102&103: Add hierarchicalName to Mailbox
138    // Version 104&105: add syncData to Message
139    // Version 106: Add certificate to HostAuth
140    // Version 107: Add a SEEN column to the message table
141    // Version 108: Add a cachedFile column to the attachments table
142    // Version 109: Migrate the account so they have the correct account manager types
143    // Version 110: Stop updating message_count, don't use auto lookback, and don't use
144    //              ping/push_hold sync states.
145
146    public static final int DATABASE_VERSION = 110;
147
148    // Any changes to the database format *must* include update-in-place code.
149    // Original version: 2
150    // Version 3: Add "sourceKey" column
151    // Version 4: Database wipe required; changing AccountManager interface w/Exchange
152    // Version 5: Database wipe required; changing AccountManager interface w/Exchange
153    // Version 6: Adding Body.mIntroText column
154    // Version 7/8: Adding quoted text start pos
155    // Version 8 is last Email1 version
156    public static final int BODY_DATABASE_VERSION = 100;
157
158    /*
159     * Internal helper method for index creation.
160     * Example:
161     * "create index message_" + MessageColumns.FLAG_READ
162     * + " on " + Message.TABLE_NAME + " (" + MessageColumns.FLAG_READ + ");"
163     */
164    /* package */
165    static String createIndex(String tableName, String columnName) {
166        return "create index " + tableName.toLowerCase() + '_' + columnName
167            + " on " + tableName + " (" + columnName + ");";
168    }
169
170    static void createMessageTable(SQLiteDatabase db) {
171        String messageColumns = MessageColumns.DISPLAY_NAME + " text, "
172            + MessageColumns.TIMESTAMP + " integer, "
173            + MessageColumns.SUBJECT + " text, "
174            + MessageColumns.FLAG_READ + " integer, "
175            + MessageColumns.FLAG_LOADED + " integer, "
176            + MessageColumns.FLAG_FAVORITE + " integer, "
177            + MessageColumns.FLAG_ATTACHMENT + " integer, "
178            + MessageColumns.FLAGS + " integer, "
179            + MessageColumns.DRAFT_INFO + " integer, "
180            + MessageColumns.MESSAGE_ID + " text, "
181            + MessageColumns.MAILBOX_KEY + " integer, "
182            + MessageColumns.ACCOUNT_KEY + " integer, "
183            + MessageColumns.FROM_LIST + " text, "
184            + MessageColumns.TO_LIST + " text, "
185            + MessageColumns.CC_LIST + " text, "
186            + MessageColumns.BCC_LIST + " text, "
187            + MessageColumns.REPLY_TO_LIST + " text, "
188            + MessageColumns.MEETING_INFO + " text, "
189            + MessageColumns.SNIPPET + " text, "
190            + MessageColumns.PROTOCOL_SEARCH_INFO + " text, "
191            + MessageColumns.THREAD_TOPIC + " text, "
192            + MessageColumns.SYNC_DATA + " text, "
193            + MessageColumns.FLAG_SEEN + " integer"
194            + ");";
195
196        // This String and the following String MUST have the same columns, except for the type
197        // of those columns!
198        String createString = " (" + EmailContent.RECORD_ID + " integer primary key autoincrement, "
199            + SyncColumns.SERVER_ID + " text, "
200            + SyncColumns.SERVER_TIMESTAMP + " integer, "
201            + messageColumns;
202
203        // For the updated and deleted tables, the id is assigned, but we do want to keep track
204        // of the ORDER of updates using an autoincrement primary key.  We use the DATA column
205        // at this point; it has no other function
206        String altCreateString = " (" + EmailContent.RECORD_ID + " integer unique, "
207            + SyncColumns.SERVER_ID + " text, "
208            + SyncColumns.SERVER_TIMESTAMP + " integer, "
209            + messageColumns;
210
211        // The three tables have the same schema
212        db.execSQL("create table " + Message.TABLE_NAME + createString);
213        db.execSQL("create table " + Message.UPDATED_TABLE_NAME + altCreateString);
214        db.execSQL("create table " + Message.DELETED_TABLE_NAME + altCreateString);
215
216        String indexColumns[] = {
217            MessageColumns.TIMESTAMP,
218            MessageColumns.FLAG_READ,
219            MessageColumns.FLAG_LOADED,
220            MessageColumns.MAILBOX_KEY,
221            SyncColumns.SERVER_ID
222        };
223
224        for (String columnName : indexColumns) {
225            db.execSQL(createIndex(Message.TABLE_NAME, columnName));
226        }
227
228        // Deleting a Message deletes all associated Attachments
229        // Deleting the associated Body cannot be done in a trigger, because the Body is stored
230        // in a separate database, and trigger cannot operate on attached databases.
231        db.execSQL("create trigger message_delete before delete on " + Message.TABLE_NAME +
232                " begin delete from " + Attachment.TABLE_NAME +
233                "  where " + AttachmentColumns.MESSAGE_KEY + "=old." + EmailContent.RECORD_ID +
234                "; end");
235
236        // Add triggers to keep unread count accurate per mailbox
237
238        // NOTE: SQLite's before triggers are not safe when recursive triggers are involved.
239        // Use caution when changing them.
240
241        // Insert a message; if flagRead is zero, add to the unread count of the message's mailbox
242        db.execSQL("create trigger unread_message_insert before insert on " + Message.TABLE_NAME +
243                " when NEW." + MessageColumns.FLAG_READ + "=0" +
244                " begin update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.UNREAD_COUNT +
245                '=' + MailboxColumns.UNREAD_COUNT + "+1" +
246                "  where " + EmailContent.RECORD_ID + "=NEW." + MessageColumns.MAILBOX_KEY +
247                "; end");
248
249        // Delete a message; if flagRead is zero, decrement the unread count of the msg's mailbox
250        db.execSQL("create trigger unread_message_delete before delete on " + Message.TABLE_NAME +
251                " when OLD." + MessageColumns.FLAG_READ + "=0" +
252                " begin update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.UNREAD_COUNT +
253                '=' + MailboxColumns.UNREAD_COUNT + "-1" +
254                "  where " + EmailContent.RECORD_ID + "=OLD." + MessageColumns.MAILBOX_KEY +
255                "; end");
256
257        // Change a message's mailbox
258        db.execSQL("create trigger unread_message_move before update of " +
259                MessageColumns.MAILBOX_KEY + " on " + Message.TABLE_NAME +
260                " when OLD." + MessageColumns.FLAG_READ + "=0" +
261                " begin update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.UNREAD_COUNT +
262                '=' + MailboxColumns.UNREAD_COUNT + "-1" +
263                "  where " + EmailContent.RECORD_ID + "=OLD." + MessageColumns.MAILBOX_KEY +
264                "; update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.UNREAD_COUNT +
265                '=' + MailboxColumns.UNREAD_COUNT + "+1" +
266                " where " + EmailContent.RECORD_ID + "=NEW." + MessageColumns.MAILBOX_KEY +
267                "; end");
268
269        // Change a message's read state
270        db.execSQL("create trigger unread_message_read before update of " +
271                MessageColumns.FLAG_READ + " on " + Message.TABLE_NAME +
272                " when OLD." + MessageColumns.FLAG_READ + "!=NEW." + MessageColumns.FLAG_READ +
273                " begin update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.UNREAD_COUNT +
274                '=' + MailboxColumns.UNREAD_COUNT + "+ case OLD." + MessageColumns.FLAG_READ +
275                " when 0 then -1 else 1 end" +
276                "  where " + EmailContent.RECORD_ID + "=OLD." + MessageColumns.MAILBOX_KEY +
277                "; end");
278    }
279
280    static void resetMessageTable(SQLiteDatabase db, int oldVersion, int newVersion) {
281        try {
282            db.execSQL("drop table " + Message.TABLE_NAME);
283            db.execSQL("drop table " + Message.UPDATED_TABLE_NAME);
284            db.execSQL("drop table " + Message.DELETED_TABLE_NAME);
285        } catch (SQLException e) {
286        }
287        createMessageTable(db);
288    }
289
290    @SuppressWarnings("deprecation")
291    static void createAccountTable(SQLiteDatabase db) {
292        String s = " (" + EmailContent.RECORD_ID + " integer primary key autoincrement, "
293            + AccountColumns.DISPLAY_NAME + " text, "
294            + AccountColumns.EMAIL_ADDRESS + " text, "
295            + AccountColumns.SYNC_KEY + " text, "
296            + AccountColumns.SYNC_LOOKBACK + " integer, "
297            + AccountColumns.SYNC_INTERVAL + " text, "
298            + AccountColumns.HOST_AUTH_KEY_RECV + " integer, "
299            + AccountColumns.HOST_AUTH_KEY_SEND + " integer, "
300            + AccountColumns.FLAGS + " integer, "
301            + AccountColumns.IS_DEFAULT + " integer, "
302            + AccountColumns.COMPATIBILITY_UUID + " text, "
303            + AccountColumns.SENDER_NAME + " text, "
304            + AccountColumns.RINGTONE_URI + " text, "
305            + AccountColumns.PROTOCOL_VERSION + " text, "
306            + AccountColumns.NEW_MESSAGE_COUNT + " integer, "
307            + AccountColumns.SECURITY_FLAGS + " integer, "
308            + AccountColumns.SECURITY_SYNC_KEY + " text, "
309            + AccountColumns.SIGNATURE + " text, "
310            + AccountColumns.POLICY_KEY + " integer"
311            + ");";
312        db.execSQL("create table " + Account.TABLE_NAME + s);
313        // Deleting an account deletes associated Mailboxes and HostAuth's
314        db.execSQL(TRIGGER_ACCOUNT_DELETE);
315    }
316
317    static void resetAccountTable(SQLiteDatabase db, int oldVersion, int newVersion) {
318        try {
319            db.execSQL("drop table " +  Account.TABLE_NAME);
320        } catch (SQLException e) {
321        }
322        createAccountTable(db);
323    }
324
325    static void createPolicyTable(SQLiteDatabase db) {
326        String s = " (" + EmailContent.RECORD_ID + " integer primary key autoincrement, "
327            + PolicyColumns.PASSWORD_MODE + " integer, "
328            + PolicyColumns.PASSWORD_MIN_LENGTH + " integer, "
329            + PolicyColumns.PASSWORD_EXPIRATION_DAYS + " integer, "
330            + PolicyColumns.PASSWORD_HISTORY + " integer, "
331            + PolicyColumns.PASSWORD_COMPLEX_CHARS + " integer, "
332            + PolicyColumns.PASSWORD_MAX_FAILS + " integer, "
333            + PolicyColumns.MAX_SCREEN_LOCK_TIME + " integer, "
334            + PolicyColumns.REQUIRE_REMOTE_WIPE + " integer, "
335            + PolicyColumns.REQUIRE_ENCRYPTION + " integer, "
336            + PolicyColumns.REQUIRE_ENCRYPTION_EXTERNAL + " integer, "
337            + PolicyColumns.REQUIRE_MANUAL_SYNC_WHEN_ROAMING + " integer, "
338            + PolicyColumns.DONT_ALLOW_CAMERA + " integer, "
339            + PolicyColumns.DONT_ALLOW_ATTACHMENTS + " integer, "
340            + PolicyColumns.DONT_ALLOW_HTML + " integer, "
341            + PolicyColumns.MAX_ATTACHMENT_SIZE + " integer, "
342            + PolicyColumns.MAX_TEXT_TRUNCATION_SIZE + " integer, "
343            + PolicyColumns.MAX_HTML_TRUNCATION_SIZE + " integer, "
344            + PolicyColumns.MAX_EMAIL_LOOKBACK + " integer, "
345            + PolicyColumns.MAX_CALENDAR_LOOKBACK + " integer, "
346            + PolicyColumns.PASSWORD_RECOVERY_ENABLED + " integer, "
347            + PolicyColumns.PROTOCOL_POLICIES_ENFORCED + " text, "
348            + PolicyColumns.PROTOCOL_POLICIES_UNSUPPORTED + " text"
349            + ");";
350        db.execSQL("create table " + Policy.TABLE_NAME + s);
351    }
352
353    static void createHostAuthTable(SQLiteDatabase db) {
354        String s = " (" + EmailContent.RECORD_ID + " integer primary key autoincrement, "
355            + HostAuthColumns.PROTOCOL + " text, "
356            + HostAuthColumns.ADDRESS + " text, "
357            + HostAuthColumns.PORT + " integer, "
358            + HostAuthColumns.FLAGS + " integer, "
359            + HostAuthColumns.LOGIN + " text, "
360            + HostAuthColumns.PASSWORD + " text, "
361            + HostAuthColumns.DOMAIN + " text, "
362            + HostAuthColumns.ACCOUNT_KEY + " integer,"
363            + HostAuthColumns.CLIENT_CERT_ALIAS + " text,"
364            + HostAuthColumns.SERVER_CERT + " blob"
365            + ");";
366        db.execSQL("create table " + HostAuth.TABLE_NAME + s);
367    }
368
369    static void resetHostAuthTable(SQLiteDatabase db, int oldVersion, int newVersion) {
370        try {
371            db.execSQL("drop table " + HostAuth.TABLE_NAME);
372        } catch (SQLException e) {
373        }
374        createHostAuthTable(db);
375    }
376
377    static void createMailboxTable(SQLiteDatabase db) {
378        String s = " (" + EmailContent.RECORD_ID + " integer primary key autoincrement, "
379            + MailboxColumns.DISPLAY_NAME + " text, "
380            + MailboxColumns.SERVER_ID + " text, "
381            + MailboxColumns.PARENT_SERVER_ID + " text, "
382            + MailboxColumns.PARENT_KEY + " integer, "
383            + MailboxColumns.ACCOUNT_KEY + " integer, "
384            + MailboxColumns.TYPE + " integer, "
385            + MailboxColumns.DELIMITER + " integer, "
386            + MailboxColumns.SYNC_KEY + " text, "
387            + MailboxColumns.SYNC_LOOKBACK + " integer, "
388            + MailboxColumns.SYNC_INTERVAL + " integer, "
389            + MailboxColumns.SYNC_TIME + " integer, "
390            + MailboxColumns.UNREAD_COUNT + " integer, "
391            + MailboxColumns.FLAG_VISIBLE + " integer, "
392            + MailboxColumns.FLAGS + " integer, "
393            + MailboxColumns.VISIBLE_LIMIT + " integer, "
394            + MailboxColumns.SYNC_STATUS + " text, "
395            + MailboxColumns.MESSAGE_COUNT + " integer not null default 0, "
396            + MailboxColumns.LAST_TOUCHED_TIME + " integer default 0, "
397            + MailboxColumns.UI_SYNC_STATUS + " integer default 0, "
398            + MailboxColumns.UI_LAST_SYNC_RESULT + " integer default 0, "
399            + MailboxColumns.LAST_NOTIFIED_MESSAGE_KEY + " integer not null default 0, "
400            + MailboxColumns.LAST_NOTIFIED_MESSAGE_COUNT + " integer not null default 0, "
401            + MailboxColumns.TOTAL_COUNT + " integer, "
402            + MailboxColumns.HIERARCHICAL_NAME + " text"
403            + ");";
404        db.execSQL("create table " + Mailbox.TABLE_NAME + s);
405        db.execSQL("create index mailbox_" + MailboxColumns.SERVER_ID
406                + " on " + Mailbox.TABLE_NAME + " (" + MailboxColumns.SERVER_ID + ")");
407        db.execSQL("create index mailbox_" + MailboxColumns.ACCOUNT_KEY
408                + " on " + Mailbox.TABLE_NAME + " (" + MailboxColumns.ACCOUNT_KEY + ")");
409        // Deleting a Mailbox deletes associated Messages in all three tables
410        db.execSQL(TRIGGER_MAILBOX_DELETE);
411    }
412
413    static void resetMailboxTable(SQLiteDatabase db, int oldVersion, int newVersion) {
414        try {
415            db.execSQL("drop table " + Mailbox.TABLE_NAME);
416        } catch (SQLException e) {
417        }
418        createMailboxTable(db);
419    }
420
421    static void createAttachmentTable(SQLiteDatabase db) {
422        String s = " (" + EmailContent.RECORD_ID + " integer primary key autoincrement, "
423            + AttachmentColumns.FILENAME + " text, "
424            + AttachmentColumns.MIME_TYPE + " text, "
425            + AttachmentColumns.SIZE + " integer, "
426            + AttachmentColumns.CONTENT_ID + " text, "
427            + AttachmentColumns.CONTENT_URI + " text, "
428            + AttachmentColumns.MESSAGE_KEY + " integer, "
429            + AttachmentColumns.LOCATION + " text, "
430            + AttachmentColumns.ENCODING + " text, "
431            + AttachmentColumns.CONTENT + " text, "
432            + AttachmentColumns.FLAGS + " integer, "
433            + AttachmentColumns.CONTENT_BYTES + " blob, "
434            + AttachmentColumns.ACCOUNT_KEY + " integer, "
435            + AttachmentColumns.UI_STATE + " integer, "
436            + AttachmentColumns.UI_DESTINATION + " integer, "
437            + AttachmentColumns.UI_DOWNLOADED_SIZE + " integer, "
438            + AttachmentColumns.CACHED_FILE + " text"
439            + ");";
440        db.execSQL("create table " + Attachment.TABLE_NAME + s);
441        db.execSQL(createIndex(Attachment.TABLE_NAME, AttachmentColumns.MESSAGE_KEY));
442    }
443
444    static void resetAttachmentTable(SQLiteDatabase db, int oldVersion, int newVersion) {
445        try {
446            db.execSQL("drop table " + Attachment.TABLE_NAME);
447        } catch (SQLException e) {
448        }
449        createAttachmentTable(db);
450    }
451
452    static void createQuickResponseTable(SQLiteDatabase db) {
453        String s = " (" + EmailContent.RECORD_ID + " integer primary key autoincrement, "
454                + QuickResponseColumns.TEXT + " text, "
455                + QuickResponseColumns.ACCOUNT_KEY + " integer"
456                + ");";
457        db.execSQL("create table " + QuickResponse.TABLE_NAME + s);
458    }
459
460    static void createBodyTable(SQLiteDatabase db) {
461        String s = " (" + EmailContent.RECORD_ID + " integer primary key autoincrement, "
462            + BodyColumns.MESSAGE_KEY + " integer, "
463            + BodyColumns.HTML_CONTENT + " text, "
464            + BodyColumns.TEXT_CONTENT + " text, "
465            + BodyColumns.HTML_REPLY + " text, "
466            + BodyColumns.TEXT_REPLY + " text, "
467            + BodyColumns.SOURCE_MESSAGE_KEY + " text, "
468            + BodyColumns.INTRO_TEXT + " text, "
469            + BodyColumns.QUOTED_TEXT_START_POS + " integer"
470            + ");";
471        db.execSQL("create table " + Body.TABLE_NAME + s);
472        db.execSQL(createIndex(Body.TABLE_NAME, BodyColumns.MESSAGE_KEY));
473    }
474
475    static void upgradeBodyTable(SQLiteDatabase db, int oldVersion, int newVersion) {
476        if (oldVersion < 5) {
477            try {
478                db.execSQL("drop table " + Body.TABLE_NAME);
479                createBodyTable(db);
480                oldVersion = 5;
481            } catch (SQLException e) {
482            }
483        }
484        if (oldVersion == 5) {
485            try {
486                db.execSQL("alter table " + Body.TABLE_NAME
487                        + " add " + BodyColumns.INTRO_TEXT + " text");
488            } catch (SQLException e) {
489                // Shouldn't be needed unless we're debugging and interrupt the process
490                LogUtils.w(TAG, "Exception upgrading EmailProviderBody.db from v5 to v6", e);
491            }
492            oldVersion = 6;
493        }
494        if (oldVersion == 6 || oldVersion == 7) {
495            try {
496                db.execSQL("alter table " + Body.TABLE_NAME
497                        + " add " + BodyColumns.QUOTED_TEXT_START_POS + " integer");
498            } catch (SQLException e) {
499                // Shouldn't be needed unless we're debugging and interrupt the process
500                LogUtils.w(TAG, "Exception upgrading EmailProviderBody.db from v6 to v8", e);
501            }
502            oldVersion = 8;
503        }
504        if (oldVersion == 8) {
505            // Move to Email2 version
506            oldVersion = 100;
507        }
508    }
509
510    protected static class BodyDatabaseHelper extends SQLiteOpenHelper {
511        BodyDatabaseHelper(Context context, String name) {
512            super(context, name, null, BODY_DATABASE_VERSION);
513        }
514
515        @Override
516        public void onCreate(SQLiteDatabase db) {
517            LogUtils.d(TAG, "Creating EmailProviderBody database");
518            createBodyTable(db);
519        }
520
521        @Override
522        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
523            upgradeBodyTable(db, oldVersion, newVersion);
524        }
525
526        @Override
527        public void onOpen(SQLiteDatabase db) {
528        }
529    }
530
531    /** Counts the number of messages in each mailbox, and updates the message count column. */
532    @VisibleForTesting
533    static void recalculateMessageCount(SQLiteDatabase db) {
534        db.execSQL("update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.MESSAGE_COUNT +
535                "= (select count(*) from " + Message.TABLE_NAME +
536                " where " + Message.MAILBOX_KEY + " = " +
537                    Mailbox.TABLE_NAME + "." + EmailContent.RECORD_ID + ")");
538    }
539
540    protected static class DatabaseHelper extends SQLiteOpenHelper {
541        Context mContext;
542
543        DatabaseHelper(Context context, String name) {
544            super(context, name, null, DATABASE_VERSION);
545            mContext = context;
546        }
547
548        @Override
549        public void onCreate(SQLiteDatabase db) {
550            LogUtils.d(TAG, "Creating EmailProvider database");
551            // Create all tables here; each class has its own method
552            createMessageTable(db);
553            createAttachmentTable(db);
554            createMailboxTable(db);
555            createHostAuthTable(db);
556            createAccountTable(db);
557            createPolicyTable(db);
558            createQuickResponseTable(db);
559        }
560
561        @Override
562        public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
563            if (oldVersion == 101 && newVersion == 100) {
564                LogUtils.d(TAG, "Downgrade from v101 to v100");
565            } else {
566                super.onDowngrade(db, oldVersion, newVersion);
567            }
568        }
569
570        @Override
571        @SuppressWarnings("deprecation")
572        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
573            // For versions prior to 5, delete all data
574            // Versions >= 5 require that data be preserved!
575            if (oldVersion < 5) {
576                android.accounts.Account[] accounts = AccountManager.get(mContext)
577                        .getAccountsByType("eas");
578                for (android.accounts.Account account: accounts) {
579                    AccountManager.get(mContext).removeAccount(account, null, null);
580                }
581                resetMessageTable(db, oldVersion, newVersion);
582                resetAttachmentTable(db, oldVersion, newVersion);
583                resetMailboxTable(db, oldVersion, newVersion);
584                resetHostAuthTable(db, oldVersion, newVersion);
585                resetAccountTable(db, oldVersion, newVersion);
586                return;
587            }
588            if (oldVersion == 5) {
589                // Message Tables: Add SyncColumns.SERVER_TIMESTAMP
590                try {
591                    db.execSQL("alter table " + Message.TABLE_NAME
592                            + " add column " + SyncColumns.SERVER_TIMESTAMP + " integer" + ";");
593                    db.execSQL("alter table " + Message.UPDATED_TABLE_NAME
594                            + " add column " + SyncColumns.SERVER_TIMESTAMP + " integer" + ";");
595                    db.execSQL("alter table " + Message.DELETED_TABLE_NAME
596                            + " add column " + SyncColumns.SERVER_TIMESTAMP + " integer" + ";");
597                } catch (SQLException e) {
598                    // Shouldn't be needed unless we're debugging and interrupt the process
599                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from v5 to v6", e);
600                }
601                oldVersion = 6;
602            }
603            if (oldVersion == 6) {
604                // Use the newer mailbox_delete trigger
605                db.execSQL("drop trigger mailbox_delete;");
606                db.execSQL(TRIGGER_MAILBOX_DELETE);
607                oldVersion = 7;
608            }
609            if (oldVersion == 7) {
610                // add the security (provisioning) column
611                try {
612                    db.execSQL("alter table " + Account.TABLE_NAME
613                            + " add column " + AccountColumns.SECURITY_FLAGS + " integer" + ";");
614                } catch (SQLException e) {
615                    // Shouldn't be needed unless we're debugging and interrupt the process
616                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 7 to 8 " + e);
617                }
618                oldVersion = 8;
619            }
620            if (oldVersion == 8) {
621                // accounts: add security sync key & user signature columns
622                try {
623                    db.execSQL("alter table " + Account.TABLE_NAME
624                            + " add column " + AccountColumns.SECURITY_SYNC_KEY + " text" + ";");
625                    db.execSQL("alter table " + Account.TABLE_NAME
626                            + " add column " + AccountColumns.SIGNATURE + " text" + ";");
627                } catch (SQLException e) {
628                    // Shouldn't be needed unless we're debugging and interrupt the process
629                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 8 to 9 " + e);
630                }
631                oldVersion = 9;
632            }
633            if (oldVersion == 9) {
634                // Message: add meeting info column into Message tables
635                try {
636                    db.execSQL("alter table " + Message.TABLE_NAME
637                            + " add column " + MessageColumns.MEETING_INFO + " text" + ";");
638                    db.execSQL("alter table " + Message.UPDATED_TABLE_NAME
639                            + " add column " + MessageColumns.MEETING_INFO + " text" + ";");
640                    db.execSQL("alter table " + Message.DELETED_TABLE_NAME
641                            + " add column " + MessageColumns.MEETING_INFO + " text" + ";");
642                } catch (SQLException e) {
643                    // Shouldn't be needed unless we're debugging and interrupt the process
644                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 9 to 10 " + e);
645                }
646                oldVersion = 10;
647            }
648            if (oldVersion == 10) {
649                // Attachment: add content and flags columns
650                try {
651                    db.execSQL("alter table " + Attachment.TABLE_NAME
652                            + " add column " + AttachmentColumns.CONTENT + " text" + ";");
653                    db.execSQL("alter table " + Attachment.TABLE_NAME
654                            + " add column " + AttachmentColumns.FLAGS + " integer" + ";");
655                } catch (SQLException e) {
656                    // Shouldn't be needed unless we're debugging and interrupt the process
657                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 10 to 11 " + e);
658                }
659                oldVersion = 11;
660            }
661            if (oldVersion == 11) {
662                // Attachment: add content_bytes
663                try {
664                    db.execSQL("alter table " + Attachment.TABLE_NAME
665                            + " add column " + AttachmentColumns.CONTENT_BYTES + " blob" + ";");
666                } catch (SQLException e) {
667                    // Shouldn't be needed unless we're debugging and interrupt the process
668                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 11 to 12 " + e);
669                }
670                oldVersion = 12;
671            }
672            if (oldVersion == 12) {
673                try {
674                    db.execSQL("alter table " + Mailbox.TABLE_NAME
675                            + " add column " + Mailbox.MESSAGE_COUNT
676                                    +" integer not null default 0" + ";");
677                    recalculateMessageCount(db);
678                } catch (SQLException e) {
679                    // Shouldn't be needed unless we're debugging and interrupt the process
680                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 12 to 13 " + e);
681                }
682                oldVersion = 13;
683            }
684            if (oldVersion == 13) {
685                try {
686                    db.execSQL("alter table " + Message.TABLE_NAME
687                            + " add column " + Message.SNIPPET
688                                    +" text" + ";");
689                } catch (SQLException e) {
690                    // Shouldn't be needed unless we're debugging and interrupt the process
691                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 13 to 14 " + e);
692                }
693                oldVersion = 14;
694            }
695            if (oldVersion == 14) {
696                try {
697                    db.execSQL("alter table " + Message.DELETED_TABLE_NAME
698                            + " add column " + Message.SNIPPET +" text" + ";");
699                    db.execSQL("alter table " + Message.UPDATED_TABLE_NAME
700                            + " add column " + Message.SNIPPET +" text" + ";");
701                } catch (SQLException e) {
702                    // Shouldn't be needed unless we're debugging and interrupt the process
703                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 14 to 15 " + e);
704                }
705                oldVersion = 15;
706            }
707            if (oldVersion == 15) {
708                try {
709                    db.execSQL("alter table " + Attachment.TABLE_NAME
710                            + " add column " + Attachment.ACCOUNT_KEY +" integer" + ";");
711                    // Update all existing attachments to add the accountKey data
712                    db.execSQL("update " + Attachment.TABLE_NAME + " set " +
713                            Attachment.ACCOUNT_KEY + "= (SELECT " + Message.TABLE_NAME + "." +
714                            Message.ACCOUNT_KEY + " from " + Message.TABLE_NAME + " where " +
715                            Message.TABLE_NAME + "." + Message.RECORD_ID + " = " +
716                            Attachment.TABLE_NAME + "." + Attachment.MESSAGE_KEY + ")");
717                } catch (SQLException e) {
718                    // Shouldn't be needed unless we're debugging and interrupt the process
719                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 15 to 16 " + e);
720                }
721                oldVersion = 16;
722            }
723            if (oldVersion == 16) {
724                try {
725                    db.execSQL("alter table " + Mailbox.TABLE_NAME
726                            + " add column " + Mailbox.PARENT_KEY + " integer;");
727                } catch (SQLException e) {
728                    // Shouldn't be needed unless we're debugging and interrupt the process
729                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 16 to 17 " + e);
730                }
731                oldVersion = 17;
732            }
733            if (oldVersion == 17) {
734                upgradeFromVersion17ToVersion18(db);
735                oldVersion = 18;
736            }
737            if (oldVersion == 18) {
738                try {
739                    db.execSQL("alter table " + Account.TABLE_NAME
740                            + " add column " + Account.POLICY_KEY + " integer;");
741                    db.execSQL("drop trigger account_delete;");
742                    db.execSQL(TRIGGER_ACCOUNT_DELETE);
743                    createPolicyTable(db);
744                    convertPolicyFlagsToPolicyTable(db);
745                } catch (SQLException e) {
746                    // Shouldn't be needed unless we're debugging and interrupt the process
747                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 18 to 19 " + e);
748                }
749                oldVersion = 19;
750            }
751            if (oldVersion == 19) {
752                try {
753                    db.execSQL("alter table " + Policy.TABLE_NAME
754                            + " add column " + PolicyColumns.REQUIRE_MANUAL_SYNC_WHEN_ROAMING +
755                            " integer;");
756                    db.execSQL("alter table " + Policy.TABLE_NAME
757                            + " add column " + PolicyColumns.DONT_ALLOW_CAMERA + " integer;");
758                    db.execSQL("alter table " + Policy.TABLE_NAME
759                            + " add column " + PolicyColumns.DONT_ALLOW_ATTACHMENTS + " integer;");
760                    db.execSQL("alter table " + Policy.TABLE_NAME
761                            + " add column " + PolicyColumns.DONT_ALLOW_HTML + " integer;");
762                    db.execSQL("alter table " + Policy.TABLE_NAME
763                            + " add column " + PolicyColumns.MAX_ATTACHMENT_SIZE + " integer;");
764                    db.execSQL("alter table " + Policy.TABLE_NAME
765                            + " add column " + PolicyColumns.MAX_TEXT_TRUNCATION_SIZE +
766                            " integer;");
767                    db.execSQL("alter table " + Policy.TABLE_NAME
768                            + " add column " + PolicyColumns.MAX_HTML_TRUNCATION_SIZE +
769                            " integer;");
770                    db.execSQL("alter table " + Policy.TABLE_NAME
771                            + " add column " + PolicyColumns.MAX_EMAIL_LOOKBACK + " integer;");
772                    db.execSQL("alter table " + Policy.TABLE_NAME
773                            + " add column " + PolicyColumns.MAX_CALENDAR_LOOKBACK + " integer;");
774                    db.execSQL("alter table " + Policy.TABLE_NAME
775                            + " add column " + PolicyColumns.PASSWORD_RECOVERY_ENABLED +
776                            " integer;");
777                } catch (SQLException e) {
778                    // Shouldn't be needed unless we're debugging and interrupt the process
779                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 19 to 20 " + e);
780                }
781                oldVersion = 20;
782            }
783            if (oldVersion == 20) {
784                oldVersion = 21;
785            }
786            if (oldVersion == 21) {
787                upgradeFromVersion21ToVersion22(db, mContext);
788                oldVersion = 22;
789            }
790            if (oldVersion == 22) {
791                upgradeFromVersion22ToVersion23(db);
792                oldVersion = 23;
793            }
794            if (oldVersion == 23) {
795                upgradeFromVersion23ToVersion24(db);
796                oldVersion = 24;
797            }
798            if (oldVersion == 24) {
799                upgradeFromVersion24ToVersion25(db);
800                oldVersion = 25;
801            }
802            if (oldVersion == 25) {
803                upgradeFromVersion25ToVersion26(db);
804                oldVersion = 26;
805            }
806            if (oldVersion == 26) {
807                try {
808                    db.execSQL("alter table " + Message.TABLE_NAME
809                            + " add column " + Message.PROTOCOL_SEARCH_INFO + " text;");
810                    db.execSQL("alter table " + Message.DELETED_TABLE_NAME
811                            + " add column " + Message.PROTOCOL_SEARCH_INFO +" text" + ";");
812                    db.execSQL("alter table " + Message.UPDATED_TABLE_NAME
813                            + " add column " + Message.PROTOCOL_SEARCH_INFO +" text" + ";");
814                } catch (SQLException e) {
815                    // Shouldn't be needed unless we're debugging and interrupt the process
816                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 26 to 27 " + e);
817                }
818                oldVersion = 27;
819            }
820            if (oldVersion == 27) {
821                oldVersion = 28;
822            }
823            if (oldVersion == 28) {
824                try {
825                    db.execSQL("alter table " + Policy.TABLE_NAME
826                            + " add column " + Policy.PROTOCOL_POLICIES_ENFORCED + " text;");
827                    db.execSQL("alter table " + Policy.TABLE_NAME
828                            + " add column " + Policy.PROTOCOL_POLICIES_UNSUPPORTED + " text;");
829                } catch (SQLException e) {
830                    // Shouldn't be needed unless we're debugging and interrupt the process
831                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 28 to 29 " + e);
832                }
833                oldVersion = 29;
834            }
835            if (oldVersion == 29) {
836                upgradeFromVersion29ToVersion30(db);
837                oldVersion = 30;
838            }
839            if (oldVersion == 30) {
840                try {
841                    db.execSQL("alter table " + Mailbox.TABLE_NAME
842                            + " add column " + Mailbox.UI_SYNC_STATUS + " integer;");
843                    db.execSQL("alter table " + Mailbox.TABLE_NAME
844                            + " add column " + Mailbox.UI_LAST_SYNC_RESULT + " integer;");
845                } catch (SQLException e) {
846                    // Shouldn't be needed unless we're debugging and interrupt the process
847                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 30 to 31 " + e);
848                }
849                oldVersion = 31;
850            }
851            if (oldVersion == 31) {
852                try {
853                    db.execSQL("alter table " + Mailbox.TABLE_NAME
854                            + " add column " + Mailbox.LAST_NOTIFIED_MESSAGE_KEY + " integer;");
855                    db.execSQL("alter table " + Mailbox.TABLE_NAME
856                            + " add column " + Mailbox.LAST_NOTIFIED_MESSAGE_COUNT + " integer;");
857                    db.execSQL("update Mailbox set " + Mailbox.LAST_NOTIFIED_MESSAGE_KEY +
858                            "=0 where " + Mailbox.LAST_NOTIFIED_MESSAGE_KEY + " IS NULL");
859                    db.execSQL("update Mailbox set " + Mailbox.LAST_NOTIFIED_MESSAGE_COUNT +
860                            "=0 where " + Mailbox.LAST_NOTIFIED_MESSAGE_COUNT + " IS NULL");
861                } catch (SQLException e) {
862                    // Shouldn't be needed unless we're debugging and interrupt the process
863                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 31 to 32 " + e);
864                }
865                oldVersion = 32;
866            }
867            if (oldVersion == 32) {
868                try {
869                    db.execSQL("alter table " + Attachment.TABLE_NAME
870                            + " add column " + Attachment.UI_STATE + " integer;");
871                    db.execSQL("alter table " + Attachment.TABLE_NAME
872                            + " add column " + Attachment.UI_DESTINATION + " integer;");
873                    db.execSQL("alter table " + Attachment.TABLE_NAME
874                            + " add column " + Attachment.UI_DOWNLOADED_SIZE + " integer;");
875                    // If we have a contentUri then the attachment is saved
876                    // uiDestination of 0 = "cache", so we don't have to set this
877                    db.execSQL("update " + Attachment.TABLE_NAME + " set " + Attachment.UI_STATE +
878                            "=" + UIProvider.AttachmentState.SAVED + " where " +
879                            AttachmentColumns.CONTENT_URI + " is not null;");
880                } catch (SQLException e) {
881                    // Shouldn't be needed unless we're debugging and interrupt the process
882                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 32 to 33 " + e);
883                }
884                oldVersion = 33;
885            }
886            if (oldVersion == 33) {
887                try {
888                    db.execSQL("alter table " + Mailbox.TABLE_NAME
889                            + " add column " + MailboxColumns.TOTAL_COUNT + " integer;");
890                } catch (SQLException e) {
891                    // Shouldn't be needed unless we're debugging and interrupt the process
892                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 33 to 34 " + e);
893                }
894                oldVersion = 34;
895            }
896            if (oldVersion == 34) {
897                try {
898                    db.execSQL("update " + Mailbox.TABLE_NAME + " set " +
899                            MailboxColumns.LAST_TOUCHED_TIME + " = " +
900                            Mailbox.DRAFTS_DEFAULT_TOUCH_TIME + " WHERE " + MailboxColumns.TYPE +
901                            " = " + Mailbox.TYPE_DRAFTS);
902                    db.execSQL("update " + Mailbox.TABLE_NAME + " set " +
903                            MailboxColumns.LAST_TOUCHED_TIME + " = " +
904                            Mailbox.SENT_DEFAULT_TOUCH_TIME + " WHERE " + MailboxColumns.TYPE +
905                            " = " + Mailbox.TYPE_SENT);
906                } catch (SQLException e) {
907                    // Shouldn't be needed unless we're debugging and interrupt the process
908                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 34 to 35 " + e);
909                }
910                oldVersion = 35;
911            }
912            if (oldVersion == 35 || oldVersion == 36) {
913                try {
914                    // Set "supports settings" for EAS mailboxes
915                    db.execSQL("update " + Mailbox.TABLE_NAME + " set " +
916                            MailboxColumns.FLAGS + "=" + MailboxColumns.FLAGS + "|" +
917                            Mailbox.FLAG_SUPPORTS_SETTINGS + " where (" +
918                            MailboxColumns.FLAGS + "&" + Mailbox.FLAG_HOLDS_MAIL + ")!=0 and " +
919                            MailboxColumns.ACCOUNT_KEY + " IN (SELECT " + Account.TABLE_NAME +
920                            "." + AccountColumns.ID + " from " + Account.TABLE_NAME + "," +
921                            HostAuth.TABLE_NAME + " where " + Account.TABLE_NAME + "." +
922                            AccountColumns.HOST_AUTH_KEY_RECV + "=" + HostAuth.TABLE_NAME + "." +
923                            HostAuthColumns.ID + " and " + HostAuthColumns.PROTOCOL + "='" +
924                            LEGACY_SCHEME_EAS + "')");
925                } catch (SQLException e) {
926                    // Shouldn't be needed unless we're debugging and interrupt the process
927                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 35 to 36 " + e);
928                }
929                oldVersion = 37;
930            }
931            if (oldVersion == 37) {
932                try {
933                    db.execSQL("alter table " + Message.TABLE_NAME
934                            + " add column " + MessageColumns.THREAD_TOPIC + " text;");
935                } catch (SQLException e) {
936                    // Shouldn't be needed unless we're debugging and interrupt the process
937                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 37 to 38 " + e);
938                }
939                oldVersion = 38;
940            }
941            if (oldVersion == 38) {
942                try {
943                    db.execSQL("alter table " + Message.DELETED_TABLE_NAME
944                            + " add column " + MessageColumns.THREAD_TOPIC + " text;");
945                    db.execSQL("alter table " + Message.UPDATED_TABLE_NAME
946                            + " add column " + MessageColumns.THREAD_TOPIC + " text;");
947                } catch (SQLException e) {
948                    // Shouldn't be needed unless we're debugging and interrupt the process
949                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 38 to 39 " + e);
950                }
951                oldVersion = 39;
952            }
953            if (oldVersion == 39) {
954                upgradeToEmail2(db);
955                oldVersion = 100;
956            }
957            if (oldVersion >= 100 && oldVersion < 103) {
958                try {
959                    db.execSQL("alter table " + Mailbox.TABLE_NAME
960                            + " add " + MailboxColumns.HIERARCHICAL_NAME + " text");
961                } catch (SQLException e) {
962                    // Shouldn't be needed unless we're debugging and interrupt the process
963                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from v10x to v103", e);
964                }
965                oldVersion = 103;
966            }
967            if (oldVersion == 103) {
968                try {
969                    db.execSQL("alter table " + Message.TABLE_NAME
970                            + " add " + MessageColumns.SYNC_DATA + " text");
971                } catch (SQLException e) {
972                    // Shouldn't be needed unless we're debugging and interrupt the process
973                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from v103 to v104", e);
974                }
975                oldVersion = 104;
976            }
977            if (oldVersion == 104) {
978                try {
979                    db.execSQL("alter table " + Message.UPDATED_TABLE_NAME
980                            + " add " + MessageColumns.SYNC_DATA + " text");
981                    db.execSQL("alter table " + Message.DELETED_TABLE_NAME
982                            + " add " + MessageColumns.SYNC_DATA + " text");
983                } catch (SQLException e) {
984                    // Shouldn't be needed unless we're debugging and interrupt the process
985                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from v104 to v105", e);
986                }
987                oldVersion = 105;
988            }
989            if (oldVersion == 105) {
990                try {
991                    db.execSQL("alter table " + HostAuth.TABLE_NAME
992                            + " add " + HostAuthColumns.SERVER_CERT + " blob");
993                } catch (SQLException e) {
994                    // Shouldn't be needed unless we're debugging and interrupt the process
995                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from v105 to v106", e);
996                }
997                oldVersion = 106;
998            }
999            if (oldVersion == 106) {
1000                try {
1001                    db.execSQL("alter table " + Message.TABLE_NAME
1002                            + " add " + MessageColumns.FLAG_SEEN + " integer");
1003                    db.execSQL("alter table " + Message.UPDATED_TABLE_NAME
1004                            + " add " + MessageColumns.FLAG_SEEN + " integer");
1005                    db.execSQL("alter table " + Message.DELETED_TABLE_NAME
1006                            + " add " + MessageColumns.FLAG_SEEN + " integer");
1007                } catch (SQLException e) {
1008                    // Shouldn't be needed unless we're debugging and interrupt the process
1009                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from v106 to v107", e);
1010                }
1011                oldVersion = 107;
1012            }
1013            if (oldVersion == 107) {
1014                try {
1015                    db.execSQL("alter table " + Attachment.TABLE_NAME
1016                            + " add column " + Attachment.CACHED_FILE +" text" + ";");
1017                } catch (SQLException e) {
1018                    // Shouldn't be needed unless we're debugging and interrupt the process
1019                    LogUtils.w(TAG, "Exception upgrading EmailProvider.db from v107 to v108", e);
1020                }
1021                oldVersion = 108;
1022            }
1023            if (oldVersion == 108) {
1024                // Migrate the accounts with the correct account type
1025                migrateLegacyAccounts(db, mContext);
1026                oldVersion = 109;
1027            }
1028            if (oldVersion == 109) {
1029                // Delete the triggers that maintained message_count.
1030                db.execSQL("drop trigger message_count_message_insert");
1031                db.execSQL("drop trigger message_count_message_delete");
1032                db.execSQL("drop trigger message_count_message_move");
1033
1034                // Fix any mailboxes that have ping or push_hold states.
1035                db.execSQL("update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.SYNC_INTERVAL
1036                        + "=" + Mailbox.CHECK_INTERVAL_PUSH + " where "
1037                        + MailboxColumns.SYNC_INTERVAL + "<" + Mailbox.CHECK_INTERVAL_PUSH);
1038
1039                // Fix invalid syncLookback values.
1040                db.execSQL("update " + Account.TABLE_NAME + " set " + AccountColumns.SYNC_LOOKBACK
1041                        + "=null where " + AccountColumns.SYNC_LOOKBACK +"<"
1042                        + SyncWindow.SYNC_WINDOW_1_DAY);
1043                db.execSQL("update " + Mailbox.TABLE_NAME + " set " + MailboxColumns.SYNC_LOOKBACK
1044                        + "=null where " + MailboxColumns.SYNC_LOOKBACK + "<"
1045                        + SyncWindow.SYNC_WINDOW_1_DAY);
1046            }
1047        }
1048
1049        @Override
1050        public void onOpen(SQLiteDatabase db) {
1051            try {
1052                // Cleanup some nasty records
1053                db.execSQL("DELETE FROM " + Account.TABLE_NAME
1054                        + " WHERE " + AccountColumns.DISPLAY_NAME + " ISNULL;");
1055                db.execSQL("DELETE FROM " + HostAuth.TABLE_NAME
1056                        + " WHERE " + HostAuthColumns.PROTOCOL + " ISNULL;");
1057            } catch (SQLException e) {
1058                // Shouldn't be needed unless we're debugging and interrupt the process
1059                LogUtils.e(TAG, e, "Exception cleaning EmailProvider.db");
1060            }
1061        }
1062    }
1063
1064    @VisibleForTesting
1065    @SuppressWarnings("deprecation")
1066    static void convertPolicyFlagsToPolicyTable(SQLiteDatabase db) {
1067        Cursor c = db.query(Account.TABLE_NAME,
1068                new String[] {EmailContent.RECORD_ID /*0*/, AccountColumns.SECURITY_FLAGS /*1*/},
1069                AccountColumns.SECURITY_FLAGS + ">0", null, null, null, null);
1070        try {
1071            ContentValues cv = new ContentValues();
1072            String[] args = new String[1];
1073            while (c.moveToNext()) {
1074                long securityFlags = c.getLong(1 /*SECURITY_FLAGS*/);
1075                Policy policy = LegacyPolicySet.flagsToPolicy(securityFlags);
1076                long policyId = db.insert(Policy.TABLE_NAME, null, policy.toContentValues());
1077                cv.put(AccountColumns.POLICY_KEY, policyId);
1078                cv.putNull(AccountColumns.SECURITY_FLAGS);
1079                args[0] = Long.toString(c.getLong(0 /*RECORD_ID*/));
1080                db.update(Account.TABLE_NAME, cv, EmailContent.RECORD_ID + "=?", args);
1081            }
1082        } finally {
1083            c.close();
1084        }
1085    }
1086
1087    /** Upgrades the database from v17 to v18 */
1088    @VisibleForTesting
1089    static void upgradeFromVersion17ToVersion18(SQLiteDatabase db) {
1090        // Copy the displayName column to the serverId column. In v18 of the database,
1091        // we use the serverId for IMAP/POP3 mailboxes instead of overloading the
1092        // display name.
1093        //
1094        // For posterity; this is the command we're executing:
1095        //sqlite> UPDATE mailbox SET serverid=displayname WHERE mailbox._id in (
1096        //        ...> SELECT mailbox._id FROM mailbox,account,hostauth WHERE
1097        //        ...> (mailbox.parentkey isnull OR mailbox.parentkey=0) AND
1098        //        ...> mailbox.accountkey=account._id AND
1099        //        ...> account.hostauthkeyrecv=hostauth._id AND
1100        //        ...> (hostauth.protocol='imap' OR hostauth.protocol='pop3'));
1101        try {
1102            db.execSQL(
1103                    "UPDATE " + Mailbox.TABLE_NAME + " SET "
1104                    + MailboxColumns.SERVER_ID + "=" + MailboxColumns.DISPLAY_NAME
1105                    + " WHERE "
1106                    + Mailbox.TABLE_NAME + "." + MailboxColumns.ID + " IN ( SELECT "
1107                    + Mailbox.TABLE_NAME + "." + MailboxColumns.ID + " FROM "
1108                    + Mailbox.TABLE_NAME + "," + Account.TABLE_NAME + ","
1109                    + HostAuth.TABLE_NAME + " WHERE "
1110                    + "("
1111                    + Mailbox.TABLE_NAME + "." + MailboxColumns.PARENT_KEY + " isnull OR "
1112                    + Mailbox.TABLE_NAME + "." + MailboxColumns.PARENT_KEY + "=0 "
1113                    + ") AND "
1114                    + Mailbox.TABLE_NAME + "." + MailboxColumns.ACCOUNT_KEY + "="
1115                    + Account.TABLE_NAME + "." + AccountColumns.ID + " AND "
1116                    + Account.TABLE_NAME + "." + AccountColumns.HOST_AUTH_KEY_RECV + "="
1117                    + HostAuth.TABLE_NAME + "." + HostAuthColumns.ID + " AND ( "
1118                    + HostAuth.TABLE_NAME + "." + HostAuthColumns.PROTOCOL + "='imap' OR "
1119                    + HostAuth.TABLE_NAME + "." + HostAuthColumns.PROTOCOL + "='pop3' ) )");
1120        } catch (SQLException e) {
1121            // Shouldn't be needed unless we're debugging and interrupt the process
1122            LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 17 to 18 " + e);
1123        }
1124        ContentCache.invalidateAllCaches();
1125    }
1126
1127    /**
1128     * Upgrade the database from v21 to v22
1129     * This entails creating AccountManager accounts for all pop3 and imap accounts
1130     */
1131
1132    private static final String[] V21_ACCOUNT_PROJECTION =
1133        new String[] {AccountColumns.HOST_AUTH_KEY_RECV, AccountColumns.EMAIL_ADDRESS};
1134    private static final int V21_ACCOUNT_RECV = 0;
1135    private static final int V21_ACCOUNT_EMAIL = 1;
1136
1137    private static final String[] V21_HOSTAUTH_PROJECTION =
1138        new String[] {HostAuthColumns.PROTOCOL, HostAuthColumns.PASSWORD};
1139    private static final int V21_HOSTAUTH_PROTOCOL = 0;
1140    private static final int V21_HOSTAUTH_PASSWORD = 1;
1141
1142    private static void createAccountManagerAccount(Context context, String login, String type,
1143            String password) {
1144        final AccountManager accountManager = AccountManager.get(context);
1145
1146        if (isAccountPresent(accountManager, login, type)) {
1147            // The account already exists,just return
1148            return;
1149        }
1150        LogUtils.v("Email", "Creating account %s %s", login, type);
1151        final android.accounts.Account amAccount = new android.accounts.Account(login, type);
1152        accountManager.addAccountExplicitly(amAccount, password, null);
1153        ContentResolver.setIsSyncable(amAccount, EmailContent.AUTHORITY, 1);
1154        ContentResolver.setSyncAutomatically(amAccount, EmailContent.AUTHORITY, true);
1155        ContentResolver.setIsSyncable(amAccount, ContactsContract.AUTHORITY, 0);
1156        ContentResolver.setIsSyncable(amAccount, CalendarContract.AUTHORITY, 0);
1157    }
1158
1159    private static boolean isAccountPresent(AccountManager accountManager, String name,
1160            String type) {
1161        final android.accounts.Account[] amAccounts = accountManager.getAccountsByType(type);
1162        if (amAccounts != null) {
1163            for (android.accounts.Account account : amAccounts) {
1164                if (TextUtils.equals(account.name, name) && TextUtils.equals(account.type, type)) {
1165                    return true;
1166                }
1167            }
1168        }
1169        return false;
1170    }
1171
1172    @VisibleForTesting
1173    static void upgradeFromVersion21ToVersion22(SQLiteDatabase db, Context accountManagerContext) {
1174        migrateLegacyAccounts(db, accountManagerContext);
1175    }
1176
1177    private static void migrateLegacyAccounts(SQLiteDatabase db, Context accountManagerContext) {
1178        final Map<String, String> legacyToNewTypeMap = new ImmutableMap.Builder<String, String>()
1179                .put(LEGACY_SCHEME_POP3,
1180                        accountManagerContext.getString(R.string.account_manager_type_pop3))
1181                .put(LEGACY_SCHEME_IMAP,
1182                        accountManagerContext.getString(R.string.account_manager_type_legacy_imap))
1183                .put(LEGACY_SCHEME_EAS,
1184                        accountManagerContext.getString(R.string.account_manager_type_exchange))
1185                .build();
1186        try {
1187            // Loop through accounts, looking for pop/imap accounts
1188            final Cursor accountCursor = db.query(Account.TABLE_NAME, V21_ACCOUNT_PROJECTION, null,
1189                    null, null, null, null);
1190            try {
1191                final String[] hostAuthArgs = new String[1];
1192                while (accountCursor.moveToNext()) {
1193                    hostAuthArgs[0] = accountCursor.getString(V21_ACCOUNT_RECV);
1194                    // Get the "receive" HostAuth for this account
1195                    final Cursor hostAuthCursor = db.query(HostAuth.TABLE_NAME,
1196                            V21_HOSTAUTH_PROJECTION, HostAuth.RECORD_ID + "=?", hostAuthArgs,
1197                            null, null, null);
1198                    try {
1199                        if (hostAuthCursor.moveToFirst()) {
1200                            final String protocol = hostAuthCursor.getString(V21_HOSTAUTH_PROTOCOL);
1201                            // If this is a pop3 or imap account, create the account manager account
1202                            if (LEGACY_SCHEME_IMAP.equals(protocol) ||
1203                                    LEGACY_SCHEME_POP3.equals(protocol)) {
1204                                // If this is a pop3 or imap account, create the account manager
1205                                // account
1206                                if (MailActivityEmail.DEBUG) {
1207                                    LogUtils.d(TAG, "Create AccountManager account for " + protocol
1208                                            + "account: "
1209                                            + accountCursor.getString(V21_ACCOUNT_EMAIL));
1210                                }
1211                                createAccountManagerAccount(accountManagerContext,
1212                                        accountCursor.getString(V21_ACCOUNT_EMAIL),
1213                                        legacyToNewTypeMap.get(protocol),
1214                                        hostAuthCursor.getString(V21_HOSTAUTH_PASSWORD));
1215                            } else if (LEGACY_SCHEME_EAS.equals(protocol)) {
1216                                // If an EAS account, make Email sync automatically (equivalent of
1217                                // checking the "Sync Email" box in settings
1218
1219                                android.accounts.Account amAccount = new android.accounts.Account(
1220                                        accountCursor.getString(V21_ACCOUNT_EMAIL),
1221                                        legacyToNewTypeMap.get(protocol));
1222                                ContentResolver.setIsSyncable(amAccount, EmailContent.AUTHORITY, 1);
1223                                ContentResolver.setSyncAutomatically(amAccount,
1224                                        EmailContent.AUTHORITY, true);
1225                            }
1226                        }
1227                    } finally {
1228                        hostAuthCursor.close();
1229                    }
1230                }
1231            } finally {
1232                accountCursor.close();
1233            }
1234        } catch (SQLException e) {
1235            // Shouldn't be needed unless we're debugging and interrupt the process
1236            LogUtils.w(TAG, "Exception while migrating accounts " + e);
1237        }
1238    }
1239
1240    /** Upgrades the database from v22 to v23 */
1241    private static void upgradeFromVersion22ToVersion23(SQLiteDatabase db) {
1242        try {
1243            db.execSQL("alter table " + Mailbox.TABLE_NAME
1244                    + " add column " + Mailbox.LAST_TOUCHED_TIME + " integer default 0;");
1245        } catch (SQLException e) {
1246            // Shouldn't be needed unless we're debugging and interrupt the process
1247            LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 22 to 23 " + e);
1248        }
1249    }
1250
1251    /** Adds in a column for information about a client certificate to use. */
1252    private static void upgradeFromVersion23ToVersion24(SQLiteDatabase db) {
1253        try {
1254            db.execSQL("alter table " + HostAuth.TABLE_NAME
1255                    + " add column " + HostAuth.CLIENT_CERT_ALIAS + " text;");
1256        } catch (SQLException e) {
1257            // Shouldn't be needed unless we're debugging and interrupt the process
1258            LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 23 to 24 " + e);
1259        }
1260    }
1261
1262    /** Upgrades the database from v24 to v25 by creating table for quick responses */
1263    private static void upgradeFromVersion24ToVersion25(SQLiteDatabase db) {
1264        try {
1265            createQuickResponseTable(db);
1266        } catch (SQLException e) {
1267            // Shouldn't be needed unless we're debugging and interrupt the process
1268            LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 24 to 25 " + e);
1269        }
1270    }
1271
1272    private static final String[] V25_ACCOUNT_PROJECTION =
1273        new String[] {AccountColumns.ID, AccountColumns.FLAGS, AccountColumns.HOST_AUTH_KEY_RECV};
1274    private static final int V25_ACCOUNT_ID = 0;
1275    private static final int V25_ACCOUNT_FLAGS = 1;
1276    private static final int V25_ACCOUNT_RECV = 2;
1277
1278    private static final String[] V25_HOSTAUTH_PROJECTION = new String[] {HostAuthColumns.PROTOCOL};
1279    private static final int V25_HOSTAUTH_PROTOCOL = 0;
1280
1281    /** Upgrades the database from v25 to v26 by adding FLAG_SUPPORTS_SEARCH to IMAP accounts */
1282    private static void upgradeFromVersion25ToVersion26(SQLiteDatabase db) {
1283        try {
1284            // Loop through accounts, looking for imap accounts
1285            Cursor accountCursor = db.query(Account.TABLE_NAME, V25_ACCOUNT_PROJECTION, null,
1286                    null, null, null, null);
1287            ContentValues cv = new ContentValues();
1288            try {
1289                String[] hostAuthArgs = new String[1];
1290                while (accountCursor.moveToNext()) {
1291                    hostAuthArgs[0] = accountCursor.getString(V25_ACCOUNT_RECV);
1292                    // Get the "receive" HostAuth for this account
1293                    Cursor hostAuthCursor = db.query(HostAuth.TABLE_NAME,
1294                            V25_HOSTAUTH_PROJECTION, HostAuth.RECORD_ID + "=?", hostAuthArgs,
1295                            null, null, null);
1296                    try {
1297                        if (hostAuthCursor.moveToFirst()) {
1298                            String protocol = hostAuthCursor.getString(V25_HOSTAUTH_PROTOCOL);
1299                            // If this is an imap account, add the search flag
1300                            if (LEGACY_SCHEME_IMAP.equals(protocol)) {
1301                                String id = accountCursor.getString(V25_ACCOUNT_ID);
1302                                int flags = accountCursor.getInt(V25_ACCOUNT_FLAGS);
1303                                cv.put(AccountColumns.FLAGS, flags | Account.FLAGS_SUPPORTS_SEARCH);
1304                                db.update(Account.TABLE_NAME, cv, Account.RECORD_ID + "=?",
1305                                        new String[] {id});
1306                            }
1307                        }
1308                    } finally {
1309                        hostAuthCursor.close();
1310                    }
1311                }
1312            } finally {
1313                accountCursor.close();
1314            }
1315        } catch (SQLException e) {
1316            // Shouldn't be needed unless we're debugging and interrupt the process
1317            LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 25 to 26 " + e);
1318        }
1319    }
1320
1321    /** Upgrades the database from v29 to v30 by updating all address fields in Message */
1322    private static final int[] ADDRESS_COLUMN_INDICES = new int[] {
1323        Message.CONTENT_BCC_LIST_COLUMN, Message.CONTENT_CC_LIST_COLUMN,
1324        Message.CONTENT_FROM_LIST_COLUMN, Message.CONTENT_REPLY_TO_COLUMN,
1325        Message.CONTENT_TO_LIST_COLUMN
1326    };
1327    private static final String[] ADDRESS_COLUMN_NAMES = new String[] {
1328        Message.BCC_LIST, Message.CC_LIST, Message.FROM_LIST, Message.REPLY_TO_LIST, Message.TO_LIST
1329    };
1330
1331    private static void upgradeFromVersion29ToVersion30(SQLiteDatabase db) {
1332        try {
1333            // Loop through all messages, updating address columns to new format (CSV, RFC822)
1334            Cursor messageCursor = db.query(Message.TABLE_NAME, Message.CONTENT_PROJECTION, null,
1335                    null, null, null, null);
1336            ContentValues cv = new ContentValues();
1337            String[] whereArgs = new String[1];
1338            try {
1339                while (messageCursor.moveToNext()) {
1340                    for (int i = 0; i < ADDRESS_COLUMN_INDICES.length; i++) {
1341                        Address[] addrs =
1342                                Address.unpack(messageCursor.getString(ADDRESS_COLUMN_INDICES[i]));
1343                        cv.put(ADDRESS_COLUMN_NAMES[i], Address.pack(addrs));
1344                    }
1345                    whereArgs[0] = messageCursor.getString(Message.CONTENT_ID_COLUMN);
1346                    db.update(Message.TABLE_NAME, cv, WHERE_ID, whereArgs);
1347                }
1348            } finally {
1349                messageCursor.close();
1350            }
1351        } catch (SQLException e) {
1352            // Shouldn't be needed unless we're debugging and interrupt the process
1353            LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 29 to 30 " + e);
1354        }
1355    }
1356
1357    private static void upgradeToEmail2(SQLiteDatabase db) {
1358        // Perform cleanup operations from Email1 to Email2; Email1 will have added new
1359        // data that won't conform to what's expected in Email2
1360
1361        // From 31->32 upgrade
1362        try {
1363            db.execSQL("update Mailbox set " + Mailbox.LAST_NOTIFIED_MESSAGE_KEY +
1364                    "=0 where " + Mailbox.LAST_NOTIFIED_MESSAGE_KEY + " IS NULL");
1365            db.execSQL("update Mailbox set " + Mailbox.LAST_NOTIFIED_MESSAGE_COUNT +
1366                    "=0 where " + Mailbox.LAST_NOTIFIED_MESSAGE_COUNT + " IS NULL");
1367        } catch (SQLException e) {
1368            LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 31 to 32/100 " + e);
1369        }
1370
1371        // From 32->33 upgrade
1372        try {
1373            db.execSQL("update " + Attachment.TABLE_NAME + " set " + Attachment.UI_STATE +
1374                    "=" + UIProvider.AttachmentState.SAVED + " where " +
1375                    AttachmentColumns.CONTENT_URI + " is not null;");
1376        } catch (SQLException e) {
1377            LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 32 to 33/100 " + e);
1378        }
1379
1380        // From 34->35 upgrade
1381        try {
1382            db.execSQL("update " + Mailbox.TABLE_NAME + " set " +
1383                    MailboxColumns.LAST_TOUCHED_TIME + " = " +
1384                    Mailbox.DRAFTS_DEFAULT_TOUCH_TIME + " WHERE " + MailboxColumns.TYPE +
1385                    " = " + Mailbox.TYPE_DRAFTS);
1386            db.execSQL("update " + Mailbox.TABLE_NAME + " set " +
1387                    MailboxColumns.LAST_TOUCHED_TIME + " = " +
1388                    Mailbox.SENT_DEFAULT_TOUCH_TIME + " WHERE " + MailboxColumns.TYPE +
1389                    " = " + Mailbox.TYPE_SENT);
1390        } catch (SQLException e) {
1391            LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 34 to 35/100 " + e);
1392        }
1393
1394        // From 35/36->37
1395        try {
1396            db.execSQL("update " + Mailbox.TABLE_NAME + " set " +
1397                    MailboxColumns.FLAGS + "=" + MailboxColumns.FLAGS + "|" +
1398                    Mailbox.FLAG_SUPPORTS_SETTINGS + " where (" +
1399                    MailboxColumns.FLAGS + "&" + Mailbox.FLAG_HOLDS_MAIL + ")!=0 and " +
1400                    MailboxColumns.ACCOUNT_KEY + " IN (SELECT " + Account.TABLE_NAME +
1401                    "." + AccountColumns.ID + " from " + Account.TABLE_NAME + "," +
1402                    HostAuth.TABLE_NAME + " where " + Account.TABLE_NAME + "." +
1403                    AccountColumns.HOST_AUTH_KEY_RECV + "=" + HostAuth.TABLE_NAME + "." +
1404                    HostAuthColumns.ID + " and " + HostAuthColumns.PROTOCOL + "='" +
1405                    LEGACY_SCHEME_EAS + "')");
1406        } catch (SQLException e) {
1407            LogUtils.w(TAG, "Exception upgrading EmailProvider.db from 35/36 to 37/100 " + e);
1408        }
1409    }
1410}
1411