17236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project/*
27236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
37236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project *
47236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
57236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * you may not use this file except in compliance with the License.
67236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * You may obtain a copy of the License at
77236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project *
87236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
97236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project *
107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * See the License for the specific language governing permissions and
147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project * limitations under the License.
157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project */
167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectpackage com.android.providers.telephony;
187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
19f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagnerimport java.io.IOException;
20f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagnerimport java.io.InputStream;
21f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagnerimport java.io.FileInputStream;
22f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagnerimport java.io.File;
23f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagnerimport java.util.ArrayList;
24f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylorimport java.util.HashSet;
25f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylorimport java.util.Iterator;
26f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
2710faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylorimport android.content.BroadcastReceiver;
288e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagnerimport android.content.ContentValues;
297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.content.Context;
3010faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylorimport android.content.Intent;
3110faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylorimport android.content.IntentFilter;
327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.Cursor;
337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase;
347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.database.sqlite.SQLiteOpenHelper;
357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.BaseColumns;
368e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagnerimport android.provider.Telephony;
377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Mms;
387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.MmsSms;
397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Sms;
407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Threads;
417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Mms.Addr;
427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Mms.Part;
437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.Mms.Rate;
447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.provider.Telephony.MmsSms.PendingMessages;
457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectimport android.util.Log;
467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
47b1bae65bf18dc22762cf7b8210fdad836b3e4ee5Tom Taylorimport com.google.android.mms.pdu.EncodedStringValue;
48b1bae65bf18dc22762cf7b8210fdad836b3e4ee5Tom Taylorimport com.google.android.mms.pdu.PduHeaders;
49c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor
507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Projectpublic class MmsSmsDatabaseHelper extends SQLiteOpenHelper {
517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String TAG = "MmsSmsDatabaseHelper";
527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String SMS_UPDATE_THREAD_READ_BODY =
547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET read = " +
557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    CASE (SELECT COUNT(*)" +
567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "          FROM sms" +
577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "          WHERE " + Sms.READ + " = 0" +
587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "            AND " + Sms.THREAD_ID + " = threads._id)" +
597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      WHEN 0 THEN 1" +
607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      ELSE 0" +
617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    END" +
627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = new." + Sms.THREAD_ID + "; ";
637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String UPDATE_THREAD_COUNT_ON_NEW =
657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET message_count = " +
667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "     (SELECT COUNT(sms._id) FROM sms LEFT JOIN threads " +
677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      ON threads._id = " + Sms.THREAD_ID +
687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      WHERE " + Sms.THREAD_ID + " = new.thread_id" +
697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "        AND sms." + Sms.TYPE + " != 3) + " +
707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "     (SELECT COUNT(pdu._id) FROM pdu LEFT JOIN threads " +
717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      ON threads._id = " + Mms.THREAD_ID +
727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      WHERE " + Mms.THREAD_ID + " = new.thread_id" +
737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "        AND (m_type=132 OR m_type=130 OR m_type=128)" +
747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "        AND " + Mms.MESSAGE_BOX + " != 3) " +
757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = new.thread_id; ";
767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String UPDATE_THREAD_COUNT_ON_OLD =
787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET message_count = " +
797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "     (SELECT COUNT(sms._id) FROM sms LEFT JOIN threads " +
807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      ON threads._id = " + Sms.THREAD_ID +
817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      WHERE " + Sms.THREAD_ID + " = old.thread_id" +
827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "        AND sms." + Sms.TYPE + " != 3) + " +
837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "     (SELECT COUNT(pdu._id) FROM pdu LEFT JOIN threads " +
847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      ON threads._id = " + Mms.THREAD_ID +
857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      WHERE " + Mms.THREAD_ID + " = old.thread_id" +
867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "        AND (m_type=132 OR m_type=130 OR m_type=128)" +
877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "        AND " + Mms.MESSAGE_BOX + " != 3) " +
887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = old.thread_id; ";
897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE =
917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "BEGIN" +
927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET" +
937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    date = (strftime('%s','now') * 1000), " +
947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    snippet = new." + Sms.BODY + ", " +
957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    snippet_cs = 0" +
967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = new." + Sms.THREAD_ID + "; " +
977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        UPDATE_THREAD_COUNT_ON_NEW +
987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        SMS_UPDATE_THREAD_READ_BODY +
997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "END;";
1007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String PDU_UPDATE_THREAD_CONSTRAINTS =
102c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                        "  WHEN new." + Mms.MESSAGE_TYPE + "=" +
103c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                        PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF +
104c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                        "    OR new." + Mms.MESSAGE_TYPE + "=" +
105c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                        PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND +
106c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                        "    OR new." + Mms.MESSAGE_TYPE + "=" +
107c71e770495e0b4597b4b3d947cbc68a0d35051beTom Taylor                        PduHeaders.MESSAGE_TYPE_SEND_REQ + " ";
1087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1091e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor    // When looking in the pdu table for unread messages, only count messages that
1101e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor    // are displayed to the user. The constants are defined in PduHeaders and could be used
1111e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor    // here, but the string "(m_type=132 OR m_type=130 OR m_type=128)" is used throughout this
1121e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor    // file and so it is used here to be consistent.
1131e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor    //     m_type=128   = MESSAGE_TYPE_SEND_REQ
1141e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor    //     m_type=130   = MESSAGE_TYPE_NOTIFICATION_IND
1151e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor    //     m_type=132   = MESSAGE_TYPE_RETRIEVE_CONF
1167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String PDU_UPDATE_THREAD_READ_BODY =
1177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET read = " +
1187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    CASE (SELECT COUNT(*)" +
1197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "          FROM " + MmsProvider.TABLE_PDU +
1207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "          WHERE " + Mms.READ + " = 0" +
1211e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                        "            AND " + Mms.THREAD_ID + " = threads._id " +
1221e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                        "            AND (m_type=132 OR m_type=130 OR m_type=128)) " +
1237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      WHEN 0 THEN 1" +
1247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      ELSE 0" +
1257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    END" +
1267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = new." + Mms.THREAD_ID + "; ";
1277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String PDU_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE =
1297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "BEGIN" +
1307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET" +
1317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    date = (strftime('%s','now') * 1000), " +
1327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    snippet = new." + Mms.SUBJECT + ", " +
1337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    snippet_cs = new." + Mms.SUBJECT_CHARSET +
1347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = new." + Mms.THREAD_ID + "; " +
1357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        UPDATE_THREAD_COUNT_ON_NEW +
1367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        PDU_UPDATE_THREAD_READ_BODY +
1377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "END;";
1387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private static final String UPDATE_THREAD_SNIPPET_SNIPPET_CS_ON_DELETE =
1407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET snippet = " +
1417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "   (SELECT snippet FROM" +
1427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "     (SELECT date * 1000 AS date, sub AS snippet, thread_id FROM pdu" +
1437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      UNION SELECT date, body AS snippet, thread_id FROM sms)" +
1447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    WHERE thread_id = OLD.thread_id ORDER BY date DESC LIMIT 1) " +
1457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = OLD.thread_id; " +
1467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  UPDATE threads SET snippet_cs = " +
1477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "   (SELECT snippet_cs FROM" +
1487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "     (SELECT date * 1000 AS date, sub_cs AS snippet_cs, thread_id FROM pdu" +
1497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "      UNION SELECT date, 0 AS snippet_cs, thread_id FROM sms)" +
1507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "    WHERE thread_id = OLD.thread_id ORDER BY date DESC LIMIT 1) " +
1517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                        "  WHERE threads._id = OLD.thread_id; ";
1527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1535f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project
1545f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // When a part is inserted, if it is not text/plain or application/smil
1555f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // (which both can exist with text-only MMSes), then there is an attachment.
1565f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // Set has_attachment=1 in the threads table for the thread in question.
1575f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    private static final String PART_UPDATE_THREADS_ON_INSERT_TRIGGER =
1585f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "CREATE TRIGGER update_threads_on_insert_part " +
1595f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " AFTER INSERT ON part " +
1605f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " WHEN new.ct != 'text/plain' AND new.ct != 'application/smil' " +
1615f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " BEGIN " +
1625f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "  UPDATE threads SET has_attachment=1 WHERE _id IN " +
1635f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "   (SELECT pdu.thread_id FROM part JOIN pdu ON pdu._id=part.mid " +
1645f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "     WHERE part._id=new._id LIMIT 1); " +
1655f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " END";
1662ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang
1672ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang    // When the 'mid' column in the part table is updated, we need to run the trigger to update
1682ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang    // the threads table's has_attachment column, if the part is an attachment.
1692ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang    private static final String PART_UPDATE_THREADS_ON_UPDATE_TRIGGER =
1702ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        "CREATE TRIGGER update_threads_on_update_part " +
1712ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        " AFTER UPDATE of " + Part.MSG_ID + " ON part " +
1722ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        " WHEN new.ct != 'text/plain' AND new.ct != 'application/smil' " +
1732ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        " BEGIN " +
1742ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        "  UPDATE threads SET has_attachment=1 WHERE _id IN " +
1752ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        "   (SELECT pdu.thread_id FROM part JOIN pdu ON pdu._id=part.mid " +
1762ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        "     WHERE part._id=new._id LIMIT 1); " +
1772ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                        " END";
1782ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang
1792ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang
1805f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // When a part is deleted (with the same non-text/SMIL constraint as when
1815f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // we set has_attachment), update the threads table for all threads.
1825f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // Unfortunately we cannot update only the thread that the part was
1835f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // attached to, as it is possible that the part has been orphaned and
1845f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    // the message it was attached to is already gone.
1855f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    private static final String PART_UPDATE_THREADS_ON_DELETE_TRIGGER =
1865f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "CREATE TRIGGER update_threads_on_delete_part " +
1875f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " AFTER DELETE ON part " +
1885f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " WHEN old.ct != 'text/plain' AND old.ct != 'application/smil' " +
1895f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " BEGIN " +
1905f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "  UPDATE threads SET has_attachment = " +
1915f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "   CASE " +
19294489f821be2401e4a9045901d9112d42273b362Tom Taylor                        "    (SELECT COUNT(*) FROM part JOIN pdu " +
1935f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "     WHERE pdu.thread_id = threads._id " +
19494489f821be2401e4a9045901d9112d42273b362Tom Taylor                        "     AND part.ct != 'text/plain' AND part.ct != 'application/smil' " +
19594489f821be2401e4a9045901d9112d42273b362Tom Taylor                        "     AND part.mid = pdu._id)" +
1965f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "   WHEN 0 THEN 0 " +
1975f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "   ELSE 1 " +
1985f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        "   END; " +
1995f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                        " END";
200f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
2011047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang    // When the 'thread_id' column in the pdu table is updated, we need to run the trigger to update
2021047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang    // the threads table's has_attachment column, if the message has an attachment in 'part' table
2031047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang    private static final String PDU_UPDATE_THREADS_ON_UPDATE_TRIGGER =
2041047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                        "CREATE TRIGGER update_threads_on_update_pdu " +
2051047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                        " AFTER UPDATE of thread_id ON pdu " +
2061047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                        " BEGIN " +
2071047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                        "  UPDATE threads SET has_attachment=1 WHERE _id IN " +
20894489f821be2401e4a9045901d9112d42273b362Tom Taylor                        "   (SELECT pdu.thread_id FROM part JOIN pdu " +
20994489f821be2401e4a9045901d9112d42273b362Tom Taylor                        "     WHERE part.ct != 'text/plain' AND part.ct != 'application/smil' " +
21094489f821be2401e4a9045901d9112d42273b362Tom Taylor                        "     AND part.mid = pdu._id);" +
2111047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                        " END";
2121047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang
21310faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor    private static MmsSmsDatabaseHelper sInstance = null;
21410faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor    private static boolean sTriedAutoIncrement = false;
21510faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor    private static boolean sFakeLowStorageTest = false;     // for testing only
2167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    static final String DATABASE_NAME = "mmssms.db";
21882fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen    static final int DATABASE_VERSION = 60;
21910faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor    private final Context mContext;
22010faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor    private LowStorageMonitor mLowStorageMonitor;
2211ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor
2227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private MmsSmsDatabaseHelper(Context context) {
2247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        super(context, DATABASE_NAME, null, DATABASE_VERSION);
22510faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor
22610faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        mContext = context;
2277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
2287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
2297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /**
2307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * Return a singleton helper for the combined MMS and SMS
2317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     * database.
2327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project     */
2337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    /* package */ static synchronized MmsSmsDatabaseHelper getInstance(Context context) {
23410faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        if (sInstance == null) {
23510faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor            sInstance = new MmsSmsDatabaseHelper(context);
2367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
23710faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        return sInstance;
2387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
2397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
240f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor    /**
241f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor     * Look through all the recipientIds referenced by the threads and then delete any
242f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor     * unreferenced rows from the canonical_addresses table.
243f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor     */
244f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor    private static void removeUnferencedCanonicalAddresses(SQLiteDatabase db) {
24515156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor        Cursor c = db.query(MmsSmsProvider.TABLE_THREADS, new String[] { "recipient_ids" },
246f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                null, null, null, null, null);
247f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor        if (c != null) {
248f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor            try {
249f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                if (c.getCount() == 0) {
250f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                    // no threads, delete all addresses
251f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                    int rows = db.delete("canonical_addresses", null, null);
252f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                } else {
253f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                    // Find all the referenced recipient_ids from the threads. recipientIds is
254f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                    // a space-separated list of recipient ids: "1 14 21"
255f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                    HashSet<Integer> recipientIds = new HashSet<Integer>();
256f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                    while (c.moveToNext()) {
257f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                        String[] recips = c.getString(0).split(" ");
258f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                        for (String recip : recips) {
259f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                            try {
260f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                                int recipientId = Integer.parseInt(recip);
261f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                                recipientIds.add(recipientId);
262f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                            } catch (Exception e) {
263f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                            }
264f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                        }
265f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                    }
266f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                    // Now build a selection string of all the unique recipient ids
267f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                    StringBuilder sb = new StringBuilder();
268f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                    Iterator<Integer> iter = recipientIds.iterator();
269f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                    while (iter.hasNext()) {
270f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                        sb.append("_id != " + iter.next());
271f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                        if (iter.hasNext()) {
272f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                            sb.append(" AND ");
273f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                        }
274f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                    }
275f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                    if (sb.length() > 0) {
276f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                        int rows = db.delete("canonical_addresses", sb.toString(), null);
277f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                    }
278f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                }
279f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor            } finally {
280f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor                c.close();
281f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor            }
282f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor        }
283f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor    }
284f409b0e23a37080c3b8c501671c4ea436a1e6346Tom Taylor
2857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public static void updateThread(SQLiteDatabase db, long thread_id) {
2867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        if (thread_id < 0) {
2877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            updateAllThreads(db, null, null);
2887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            return;
2897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
290f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
291842e3110ccca88661d06c733b56ead009f90b988Tom Taylor        db.beginTransaction();
292842e3110ccca88661d06c733b56ead009f90b988Tom Taylor        try {
293842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            // Delete the row for this thread in the threads table if
294842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            // there are no more messages attached to it in either
295842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            // the sms or pdu tables.
29615156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor            int rows = db.delete(MmsSmsProvider.TABLE_THREADS,
297842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                      "_id = ? AND _id NOT IN" +
298842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                      "          (SELECT thread_id FROM sms " +
299842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                      "           UNION SELECT thread_id FROM pdu)",
300842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                      new String[] { String.valueOf(thread_id) });
301842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            if (rows > 0) {
302842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                // If this deleted a row, let's remove orphaned canonical_addresses and get outta here
303842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                removeUnferencedCanonicalAddresses(db);
304842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            } else {
305842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                // Update the message count in the threads table as the sum
306842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                // of all messages in both the sms and pdu tables.
307842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                db.execSQL(
308842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                        "  UPDATE threads SET message_count = " +
309842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                                "     (SELECT COUNT(sms._id) FROM sms LEFT JOIN threads " +
310842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                                "      ON threads._id = " + Sms.THREAD_ID +
311842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                                "      WHERE " + Sms.THREAD_ID + " = " + thread_id +
312842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                                "        AND sms." + Sms.TYPE + " != 3) + " +
313842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                                "     (SELECT COUNT(pdu._id) FROM pdu LEFT JOIN threads " +
314842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                                "      ON threads._id = " + Mms.THREAD_ID +
315842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                                "      WHERE " + Mms.THREAD_ID + " = " + thread_id +
316842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                                "        AND (m_type=132 OR m_type=130 OR m_type=128)" +
317842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                                "        AND " + Mms.MESSAGE_BOX + " != 3) " +
318842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                                "  WHERE threads._id = " + thread_id + ";");
319842e3110ccca88661d06c733b56ead009f90b988Tom Taylor
320842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                // Update the date and the snippet (and its character set) in
321842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                // the threads table to be that of the most recent message in
322842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                // the thread.
323842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                db.execSQL(
324842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "  UPDATE threads" +
325842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "  SET" +
326842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "  date =" +
327842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "    (SELECT date FROM" +
328842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "        (SELECT date * 1000 AS date, thread_id FROM pdu" +
329842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "         UNION SELECT date, thread_id FROM sms)" +
330842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "     WHERE thread_id = " + thread_id + " ORDER BY date DESC LIMIT 1)," +
331842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "  snippet =" +
332842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "    (SELECT snippet FROM" +
333842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "        (SELECT date * 1000 AS date, sub AS snippet, thread_id FROM pdu" +
334842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "         UNION SELECT date, body AS snippet, thread_id FROM sms)" +
335842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "     WHERE thread_id = " + thread_id + " ORDER BY date DESC LIMIT 1)," +
336842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "  snippet_cs =" +
337842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "    (SELECT snippet_cs FROM" +
338842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "        (SELECT date * 1000 AS date, sub_cs AS snippet_cs, thread_id FROM pdu" +
339842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "         UNION SELECT date, 0 AS snippet_cs, thread_id FROM sms)" +
340842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "     WHERE thread_id = " + thread_id + " ORDER BY date DESC LIMIT 1)" +
341842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                "  WHERE threads._id = " + thread_id + ";");
342842e3110ccca88661d06c733b56ead009f90b988Tom Taylor
343842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                // Update the error column of the thread to indicate if there
344842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                // are any messages in it that have failed to send.
345842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                // First check to see if there are any messages with errors in this thread.
346842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                String query = "SELECT thread_id FROM sms WHERE type=" +
347842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                        Telephony.TextBasedSmsColumns.MESSAGE_TYPE_FAILED +
348842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                        " AND thread_id = " + thread_id +
349842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                        " LIMIT 1";
350842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                int setError = 0;
351842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                Cursor c = db.rawQuery(query, null);
352842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                if (c != null) {
353842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                    try {
354842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                        setError = c.getCount();    // Because of the LIMIT 1, count will be 1 or 0.
355842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                    } finally {
356842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                        c.close();
357842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                    }
358842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                }
359842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                // What's the current state of the error flag in the threads table?
360842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                String errorQuery = "SELECT error FROM threads WHERE _id = " + thread_id;
361842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                c = db.rawQuery(errorQuery, null);
362842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                if (c != null) {
363842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                    try {
364842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                        if (c.moveToNext()) {
365842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                            int curError = c.getInt(0);
366842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                            if (curError != setError) {
367842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                                // The current thread error column differs, update it.
368842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                                db.execSQL("UPDATE threads SET error=" + setError +
369842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                                        " WHERE _id = " + thread_id);
370842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                            }
371842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                        }
372842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                    } finally {
373842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                        c.close();
3749565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                    }
3759565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                }
3769565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor            }
377842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            db.setTransactionSuccessful();
378842e3110ccca88661d06c733b56ead009f90b988Tom Taylor        } catch (Throwable ex) {
379842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            Log.e(TAG, ex.getMessage(), ex);
380842e3110ccca88661d06c733b56ead009f90b988Tom Taylor        } finally {
381842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            db.endTransaction();
3829565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor        }
3837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
384f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
3857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public static void updateAllThreads(SQLiteDatabase db, String where, String[] whereArgs) {
386842e3110ccca88661d06c733b56ead009f90b988Tom Taylor        db.beginTransaction();
387842e3110ccca88661d06c733b56ead009f90b988Tom Taylor        try {
388842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            if (where == null) {
389842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                where = "";
390842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            } else {
391842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                where = "WHERE (" + where + ")";
392842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            }
393842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            String query = "SELECT _id FROM threads WHERE _id IN " +
394842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                           "(SELECT DISTINCT thread_id FROM sms " + where + ")";
395842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            Cursor c = db.rawQuery(query, whereArgs);
396842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            if (c != null) {
397842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                try {
398842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                    while (c.moveToNext()) {
399842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                        updateThread(db, c.getInt(0));
400842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                    }
401842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                } finally {
402842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                    c.close();
4039565e7f07472931ccefbe6804234d3543f96c9b8Tom Taylor                }
4047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            }
405842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            // TODO: there are several db operations in this function. Lets wrap them in a
406842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            // transaction to make it faster.
407842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            // remove orphaned threads
40815156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor            db.delete(MmsSmsProvider.TABLE_THREADS,
409842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                    "_id NOT IN (SELECT DISTINCT thread_id FROM sms where thread_id NOT NULL " +
410842e3110ccca88661d06c733b56ead009f90b988Tom Taylor                    "UNION SELECT DISTINCT thread_id FROM pdu where thread_id NOT NULL)", null);
411842e3110ccca88661d06c733b56ead009f90b988Tom Taylor
412842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            // remove orphaned canonical_addresses
413842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            removeUnferencedCanonicalAddresses(db);
414842e3110ccca88661d06c733b56ead009f90b988Tom Taylor
415842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            db.setTransactionSuccessful();
416842e3110ccca88661d06c733b56ead009f90b988Tom Taylor        } catch (Throwable ex) {
417842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            Log.e(TAG, ex.getMessage(), ex);
418842e3110ccca88661d06c733b56ead009f90b988Tom Taylor        } finally {
419842e3110ccca88661d06c733b56ead009f90b988Tom Taylor            db.endTransaction();
4207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
4217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
422f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
4237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public static int deleteOneSms(SQLiteDatabase db, int message_id) {
4247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int thread_id = -1;
4257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Find the thread ID that the specified SMS belongs to.
4267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Cursor c = db.query("sms", new String[] { "thread_id" },
4277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                            "_id=" + message_id, null, null, null, null);
4287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        if (c != null) {
4297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            if (c.moveToFirst()) {
4307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                thread_id = c.getInt(0);
4317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            }
4327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            c.close();
4337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
4347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
4357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Delete the specified message.
4367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        int rows = db.delete("sms", "_id=" + message_id, null);
4377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        if (thread_id > 0) {
4387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            // Update its thread.
4397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project            updateThread(db, thread_id);
4407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        }
4417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        return rows;
4427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
4437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
4447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    @Override
4457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public void onCreate(SQLiteDatabase db) {
4467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        createMmsTables(db);
4477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        createSmsTables(db);
4487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        createCommonTables(db);
4497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        createCommonTriggers(db);
4507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        createMmsTriggers(db);
4518e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        createWordsTables(db);
452a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor        createIndices(db);
4538e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    }
4548e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4558e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    // When upgrading the database we need to populate the words
4568e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    // table with the rows out of sms and part.
4578e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    private void populateWordsTable(SQLiteDatabase db) {
4588e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        final String TABLE_WORDS = "words";
4598e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        {
4608e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            Cursor smsRows = db.query(
4618e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    "sms",
4628e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    new String[] { Sms._ID, Sms.BODY },
4638e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null,
4648e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null,
4658e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null,
4668e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null,
4678e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null);
4688e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            try {
4698e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                if (smsRows != null) {
4708e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    smsRows.moveToPosition(-1);
4718e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    ContentValues cv = new ContentValues();
4728e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    while (smsRows.moveToNext()) {
4738e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.clear();
4748e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4758e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        long id = smsRows.getLong(0);        // 0 for Sms._ID
4768e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        String body = smsRows.getString(1);  // 1 for Sms.BODY
4778e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4788e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.ID, id);
4798e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.INDEXED_TEXT, body);
4808e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.SOURCE_ROW_ID, id);
4818e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.TABLE_ID, 1);
4828e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        db.insert(TABLE_WORDS, Telephony.MmsSms.WordsTable.INDEXED_TEXT, cv);
4838e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    }
4848e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                }
4858e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            } finally {
4868e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                if (smsRows != null) {
4878e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    smsRows.close();
4888e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                }
4898e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            }
4908e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        }
4918e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
4928e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        {
4938e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            Cursor mmsRows = db.query(
4948e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    "part",
4958e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    new String[] { Part._ID, Part.TEXT },
4968e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    "ct = 'text/plain'",
4978e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null,
4988e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null,
4998e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null,
5008e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    null);
5018e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            try {
5028e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                if (mmsRows != null) {
5038e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    mmsRows.moveToPosition(-1);
5048e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    ContentValues cv = new ContentValues();
5058e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    while (mmsRows.moveToNext()) {
5068e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.clear();
5078e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
5088e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        long id = mmsRows.getLong(0);         // 0 for Part._ID
5098e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        String body = mmsRows.getString(1);   // 1 for Part.TEXT
5108e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
5118e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.ID, id);
5128e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.INDEXED_TEXT, body);
5138e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.SOURCE_ROW_ID, id);
5148e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        cv.put(Telephony.MmsSms.WordsTable.TABLE_ID, 1);
5158e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                        db.insert(TABLE_WORDS, Telephony.MmsSms.WordsTable.INDEXED_TEXT, cv);
5168e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    }
5178e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                }
5188e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            } finally {
5198e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                if (mmsRows != null) {
5208e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    mmsRows.close();
5218e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                }
5228e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            }
5238e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        }
5248e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    }
5258e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
5268e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner    private void createWordsTables(SQLiteDatabase db) {
5278e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        try {
5288e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            db.execSQL("CREATE VIRTUAL TABLE words USING FTS3 (_id INTEGER PRIMARY KEY, index_text TEXT, source_id INTEGER, table_to_use INTEGER);");
5298e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
5308e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            // monitor the sms table
5318e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            // NOTE don't handle inserts using a trigger because it has an unwanted
5328e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            // side effect:  the value returned for the last row ends up being the
5338e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            // id of one of the trigger insert not the original row insert.
5348e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            // Handle inserts manually in the provider.
5358e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            db.execSQL("CREATE TRIGGER sms_words_update AFTER UPDATE ON sms BEGIN UPDATE words " +
5368e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    " SET index_text = NEW.body WHERE (source_id=NEW._id AND table_to_use=1); " +
5378e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    " END;");
5388e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            db.execSQL("CREATE TRIGGER sms_words_delete AFTER DELETE ON sms BEGIN DELETE FROM " +
5398e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                    "  words WHERE source_id = OLD._id AND table_to_use = 1; END;");
5408e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
5418e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            populateWordsTable(db);
5428e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        } catch (Exception ex) {
5438e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            Log.e(TAG, "got exception creating words table: " + ex.toString());
5448e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        }
5457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
5467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
547a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor    private void createIndices(SQLiteDatabase db) {
548a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor        createThreadIdIndex(db);
549a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor    }
550a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor
551a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor    private void createThreadIdIndex(SQLiteDatabase db) {
552a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor        try {
553a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            db.execSQL("CREATE INDEX IF NOT EXISTS typeThreadIdIndex ON sms" +
554a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            " (type, thread_id);");
555a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor        } catch (Exception ex) {
556a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            Log.e(TAG, "got exception creating indices: " + ex.toString());
557a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor        }
558a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor    }
559a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor
5607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void createMmsTables(SQLiteDatabase db) {
5617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // N.B.: Whenever the columns here are changed, the columns in
5627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // {@ref MmsSmsProvider} must be changed to match.
5637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE " + MmsProvider.TABLE_PDU + " (" +
56449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   Mms._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
5657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.THREAD_ID + " INTEGER," +
5667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.DATE + " INTEGER," +
567ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   Mms.DATE_SENT + " INTEGER DEFAULT 0," +
5687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.MESSAGE_BOX + " INTEGER," +
5697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.READ + " INTEGER DEFAULT 0," +
5707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.MESSAGE_ID + " TEXT," +
5717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.SUBJECT + " TEXT," +
5727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.SUBJECT_CHARSET + " INTEGER," +
5737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.CONTENT_TYPE + " TEXT," +
5747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.CONTENT_LOCATION + " TEXT," +
5757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.EXPIRY + " INTEGER," +
5767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.MESSAGE_CLASS + " TEXT," +
5777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.MESSAGE_TYPE + " INTEGER," +
5787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.MMS_VERSION + " INTEGER," +
5797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.MESSAGE_SIZE + " INTEGER," +
5807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.PRIORITY + " INTEGER," +
5817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.READ_REPORT + " INTEGER," +
5827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.REPORT_ALLOWED + " INTEGER," +
5837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.RESPONSE_STATUS + " INTEGER," +
5847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.STATUS + " INTEGER," +
5857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.TRANSACTION_ID + " TEXT," +
5867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.RETRIEVE_STATUS + " INTEGER," +
5877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.RETRIEVE_TEXT + " TEXT," +
5887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.RETRIEVE_TEXT_CHARSET + " INTEGER," +
5897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.READ_STATUS + " INTEGER," +
5907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.CONTENT_CLASS + " INTEGER," +
5917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.RESPONSE_TEXT + " TEXT," +
5927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Mms.DELIVERY_TIME + " INTEGER," +
593a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                   Mms.DELIVERY_REPORT + " INTEGER," +
594dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                   Mms.LOCKED + " INTEGER DEFAULT 0," +
595cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                   Mms.SUB_ID + " INTEGER DEFAULT -1, " +
59649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   Mms.SEEN + " INTEGER DEFAULT 0," +
59749776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen                   Mms.CREATOR + " TEXT," +
598f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor                   Mms.TEXT_ONLY + " INTEGER DEFAULT 0" +
599a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                   ");");
6007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE " + MmsProvider.TABLE_ADDR + " (" +
6027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Addr._ID + " INTEGER PRIMARY KEY," +
6037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Addr.MSG_ID + " INTEGER," +
6047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Addr.CONTACT_ID + " INTEGER," +
6057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Addr.ADDRESS + " TEXT," +
6067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Addr.TYPE + " INTEGER," +
6077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Addr.CHARSET + " INTEGER);");
6087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE " + MmsProvider.TABLE_PART + " (" +
61049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   Part._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
6117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.MSG_ID + " INTEGER," +
6127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.SEQ + " INTEGER DEFAULT 0," +
6137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.CONTENT_TYPE + " TEXT," +
6147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.NAME + " TEXT," +
6157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.CHARSET + " INTEGER," +
6167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.CONTENT_DISPOSITION + " TEXT," +
6177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.FILENAME + " TEXT," +
6187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.CONTENT_ID + " TEXT," +
6197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.CONTENT_LOCATION + " TEXT," +
6207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.CT_START + " INTEGER," +
6217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Part.CT_TYPE + " TEXT," +
622f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                   Part._DATA + " TEXT," +
623f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                   Part.TEXT + " TEXT);");
6247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE " + MmsProvider.TABLE_RATE + " (" +
6267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Rate.SENT_TIME + " INTEGER);");
6277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE " + MmsProvider.TABLE_DRM + " (" +
6297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   BaseColumns._ID + " INTEGER PRIMARY KEY," +
6307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "_data TEXT);");
6317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
6327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
63349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor    // Unlike the other trigger-creating functions, this function can be called multiple times
63449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor    // without harm.
6357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void createMmsTriggers(SQLiteDatabase db) {
6367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Cleans up parts when a MM is deleted.
63749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS part_cleanup");
6387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER part_cleanup DELETE ON " + MmsProvider.TABLE_PDU + " " +
63949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "BEGIN " +
64049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "  DELETE FROM " + MmsProvider.TABLE_PART +
64149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "  WHERE " + Part.MSG_ID + "=old._id;" +
64249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "END;");
6437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Cleans up address info when a MM is deleted.
64549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS addr_cleanup");
6467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER addr_cleanup DELETE ON " + MmsProvider.TABLE_PDU + " " +
64749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "BEGIN " +
64849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "  DELETE FROM " + MmsProvider.TABLE_ADDR +
64949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "  WHERE " + Addr.MSG_ID + "=old._id;" +
65049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "END;");
6517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
6527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Delete obsolete delivery-report, read-report while deleting their
6537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // associated Send.req.
65449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS cleanup_delivery_and_read_report");
6557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER cleanup_delivery_and_read_report " +
65649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "AFTER DELETE ON " + MmsProvider.TABLE_PDU + " " +
65749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "WHEN old." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_SEND_REQ + " " +
65849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "BEGIN " +
65949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "  DELETE FROM " + MmsProvider.TABLE_PDU +
66049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "  WHERE (" + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_DELIVERY_IND +
66149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "    OR " + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_READ_ORIG_IND +
66249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                ")" +
66349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "    AND " + Mms.MESSAGE_ID + "=old." + Mms.MESSAGE_ID + "; " +
66449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                "END;");
66549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
66649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS update_threads_on_insert_part");
6675f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        db.execSQL(PART_UPDATE_THREADS_ON_INSERT_TRIGGER);
66849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
66949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS update_threads_on_update_part");
6702ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang        db.execSQL(PART_UPDATE_THREADS_ON_UPDATE_TRIGGER);
67149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
67249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS update_threads_on_delete_part");
6735f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        db.execSQL(PART_UPDATE_THREADS_ON_DELETE_TRIGGER);
67449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
67549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS update_threads_on_update_pdu");
6761047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        db.execSQL(PDU_UPDATE_THREADS_ON_UPDATE_TRIGGER);
67749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
67849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // Delete pending status for a message when it is deleted.
67949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS delete_mms_pending_on_delete");
68049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("CREATE TRIGGER delete_mms_pending_on_delete " +
68149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "AFTER DELETE ON " + MmsProvider.TABLE_PDU + " " +
68249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "BEGIN " +
68349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  DELETE FROM " + MmsSmsProvider.TABLE_PENDING_MSG +
68449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  WHERE " + PendingMessages.MSG_ID + "=old._id; " +
68549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "END;");
68649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
68749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // When a message is moved out of Outbox, delete its pending status.
68849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS delete_mms_pending_on_update");
68949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("CREATE TRIGGER delete_mms_pending_on_update " +
69049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "AFTER UPDATE ON " + MmsProvider.TABLE_PDU + " " +
69149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "WHEN old." + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_OUTBOX +
69249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  AND new." + Mms.MESSAGE_BOX + "!=" + Mms.MESSAGE_BOX_OUTBOX + " " +
69349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "BEGIN " +
69449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  DELETE FROM " + MmsSmsProvider.TABLE_PENDING_MSG +
69549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  WHERE " + PendingMessages.MSG_ID + "=new._id; " +
69649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "END;");
69749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
69849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // Insert pending status for M-Notification.ind or M-ReadRec.ind
69949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // when they are inserted into Inbox/Outbox.
70049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS insert_mms_pending_on_insert");
70149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("CREATE TRIGGER insert_mms_pending_on_insert " +
70249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "AFTER INSERT ON pdu " +
70349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "WHEN new." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND +
70449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  OR new." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_READ_REC_IND +
70549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   " " +
70649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "BEGIN " +
70749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  INSERT INTO " + MmsSmsProvider.TABLE_PENDING_MSG +
70849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "    (" + PendingMessages.PROTO_TYPE + "," +
70949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "     " + PendingMessages.MSG_ID + "," +
71049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "     " + PendingMessages.MSG_TYPE + "," +
71149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "     " + PendingMessages.ERROR_TYPE + "," +
71249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "     " + PendingMessages.ERROR_CODE + "," +
71349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "     " + PendingMessages.RETRY_INDEX + "," +
71449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "     " + PendingMessages.DUE_TIME + ") " +
71549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  VALUES " +
71649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "    (" + MmsSms.MMS_PROTO + "," +
71749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "      new." + BaseColumns._ID + "," +
71849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "      new." + Mms.MESSAGE_TYPE + ",0,0,0,0);" +
71949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "END;");
72049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
72149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
72249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // Insert pending status for M-Send.req when it is moved into Outbox.
72349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS insert_mms_pending_on_update");
72449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("CREATE TRIGGER insert_mms_pending_on_update " +
72549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "AFTER UPDATE ON pdu " +
72649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "WHEN new." + Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_SEND_REQ +
72749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  AND new." + Mms.MESSAGE_BOX + "=" + Mms.MESSAGE_BOX_OUTBOX +
72849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  AND old." + Mms.MESSAGE_BOX + "!=" + Mms.MESSAGE_BOX_OUTBOX + " " +
72949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "BEGIN " +
73049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  INSERT INTO " + MmsSmsProvider.TABLE_PENDING_MSG +
73149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "    (" + PendingMessages.PROTO_TYPE + "," +
73249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "     " + PendingMessages.MSG_ID + "," +
73349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "     " + PendingMessages.MSG_TYPE + "," +
73449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "     " + PendingMessages.ERROR_TYPE + "," +
73549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "     " + PendingMessages.ERROR_CODE + "," +
73649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "     " + PendingMessages.RETRY_INDEX + "," +
73749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "     " + PendingMessages.DUE_TIME + ") " +
73849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  VALUES " +
73949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "    (" + MmsSms.MMS_PROTO + "," +
74049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "      new." + BaseColumns._ID + "," +
74149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "      new." + Mms.MESSAGE_TYPE + ",0,0,0,0);" +
74249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "END;");
74349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
74449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // monitor the mms table
74549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS mms_words_update");
74649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("CREATE TRIGGER mms_words_update AFTER UPDATE ON part BEGIN UPDATE words " +
74749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                " SET index_text = NEW.text WHERE (source_id=NEW._id AND table_to_use=2); " +
74849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                " END;");
74949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
75049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS mms_words_delete");
75149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("CREATE TRIGGER mms_words_delete AFTER DELETE ON part BEGIN DELETE FROM " +
75249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                " words WHERE source_id = OLD._id AND table_to_use = 2; END;");
75349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
75449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // Updates threads table whenever a message in pdu is updated.
75549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS pdu_update_thread_date_subject_on_update");
75649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("CREATE TRIGGER pdu_update_thread_date_subject_on_update AFTER" +
75749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  UPDATE OF " + Mms.DATE + ", " + Mms.SUBJECT + ", " + Mms.MESSAGE_BOX +
75849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  ON " + MmsProvider.TABLE_PDU + " " +
75949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   PDU_UPDATE_THREAD_CONSTRAINTS +
76049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   PDU_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE);
76149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
76249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // Update threads table whenever a message in pdu is deleted
76349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS pdu_update_thread_on_delete");
76449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("CREATE TRIGGER pdu_update_thread_on_delete " +
76549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "AFTER DELETE ON pdu " +
76649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "BEGIN " +
76749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  UPDATE threads SET " +
76849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "     date = (strftime('%s','now') * 1000)" +
76949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  WHERE threads._id = old." + Mms.THREAD_ID + "; " +
77049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   UPDATE_THREAD_COUNT_ON_OLD +
77149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   UPDATE_THREAD_SNIPPET_SNIPPET_CS_ON_DELETE +
77249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "END;");
77349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
77449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // Updates threads table whenever a message is added to pdu.
77549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS pdu_update_thread_on_insert");
77649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("CREATE TRIGGER pdu_update_thread_on_insert AFTER INSERT ON " +
77749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   MmsProvider.TABLE_PDU + " " +
77849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   PDU_UPDATE_THREAD_CONSTRAINTS +
77949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   PDU_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE);
78049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
78149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // Updates threads table whenever a message in pdu is updated.
78249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS pdu_update_thread_read_on_update");
78349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("CREATE TRIGGER pdu_update_thread_read_on_update AFTER" +
78449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  UPDATE OF " + Mms.READ +
78549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  ON " + MmsProvider.TABLE_PDU + " " +
78649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   PDU_UPDATE_THREAD_CONSTRAINTS +
78749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "BEGIN " +
78849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   PDU_UPDATE_THREAD_READ_BODY +
78949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "END;");
79049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
79149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // Update the error flag of threads when delete pending message.
79249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS update_threads_error_on_delete_mms");
79349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("CREATE TRIGGER update_threads_error_on_delete_mms " +
79449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  BEFORE DELETE ON pdu" +
79549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  WHEN OLD._id IN (SELECT DISTINCT msg_id" +
79649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "                   FROM pending_msgs" +
79749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "                   WHERE err_type >= 10) " +
79849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "BEGIN " +
79949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  UPDATE threads SET error = error - 1" +
80049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  WHERE _id = OLD.thread_id; " +
80149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "END;");
80249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
80349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // Update the error flag of threads while moving an MM out of Outbox,
80449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // which was failed to be sent permanently.
80549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS update_threads_error_on_move_mms");
80649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("CREATE TRIGGER update_threads_error_on_move_mms " +
80749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  BEFORE UPDATE OF msg_box ON pdu " +
80849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  WHEN (OLD.msg_box = 4 AND NEW.msg_box != 4) " +
80949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  AND (OLD._id IN (SELECT DISTINCT msg_id" +
81049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "                   FROM pending_msgs" +
81149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "                   WHERE err_type >= 10)) " +
81249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "BEGIN " +
81349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  UPDATE threads SET error = error - 1" +
81449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "  WHERE _id = OLD.thread_id; " +
81549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                   "END;");
8167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
8177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void createSmsTables(SQLiteDatabase db) {
8197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // N.B.: Whenever the columns here are changed, the columns in
8207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // {@ref MmsSmsProvider} must be changed to match.
8217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE sms (" +
8227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "_id INTEGER PRIMARY KEY," +
8237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "thread_id INTEGER," +
8247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "address TEXT," +
8257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "person INTEGER," +
8267236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "date INTEGER," +
827ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   "date_sent INTEGER DEFAULT 0," +
8287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "protocol INTEGER," +
8297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "read INTEGER DEFAULT 0," +
8307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "status INTEGER DEFAULT -1," + // a TP-Status value
8317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                                                  // or -1 if it
8327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                                                  // status hasn't
8337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                                                  // been received
8347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "type INTEGER," +
8357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "reply_path_present INTEGER," +
8367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "subject TEXT," +
8377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "body TEXT," +
838a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                   "service_center TEXT," +
8397d4e56b5fb5726342a3e0ebfba91dac48f56c107Tom Taylor                   "locked INTEGER DEFAULT 0," +
840cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                   "sub_id INTEGER DEFAULT -1, " +
841dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                   "error_code INTEGER DEFAULT 0," +
84249776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen                   "creator TEXT," +
8438a4060ec0c2433ceeb619a3a35fba5aabedbc1c6Tom Taylor                   "seen INTEGER DEFAULT 0" +
844a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                   ");");
8457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        /**
8477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * This table is used by the SMS dispatcher to hold
8487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * incomplete partial messages until all the parts arrive.
8497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         */
8507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE raw (" +
8517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "_id INTEGER PRIMARY KEY," +
8527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "date INTEGER," +
8537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "reference_number INTEGER," + // one per full message
8547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "count INTEGER," + // the number of parts
8557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "sequence INTEGER," + // the part number of this message
8567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "destination_port INTEGER," +
8577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "address TEXT," +
858cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                   "sub_id INTEGER DEFAULT -1, " +
8597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "pdu TEXT);"); // the raw PDU for this part
8607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE attachments (" +
8627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "sms_id INTEGER," +
8637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "content_url TEXT," +
8647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "offset INTEGER);");
8657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        /**
8677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * This table is used by the SMS dispatcher to hold pending
8687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * delivery status report intents.
8697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         */
8707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE sr_pending (" +
8717236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "reference_number INTEGER," +
8727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "action TEXT," +
8737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "data TEXT);");
8747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
8757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void createCommonTables(SQLiteDatabase db) {
8777236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // TODO Ensure that each entry is removed when the last use of
8787236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // any address equivalent to its address is removed.
8797236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8807236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        /**
8817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * This table maps the first instance seen of any particular
8827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * MMS/SMS address to an ID, which is then used as its
8837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * canonical representation.  If the same address or an
8847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * equivalent address (as determined by our Sqlite
8857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * PHONE_NUMBERS_EQUAL extension) is seen later, this same ID
88609710cec4926bcd3708376face04507e661bcc02Tom Taylor         * will be used. The _id is created with AUTOINCREMENT so it
88709710cec4926bcd3708376face04507e661bcc02Tom Taylor         * will never be reused again if a recipient is deleted.
8887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         */
8897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE canonical_addresses (" +
89009710cec4926bcd3708376face04507e661bcc02Tom Taylor                   "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
8917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "address TEXT);");
8927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
8937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        /**
8947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * This table maps the subject and an ordered set of recipient
8957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * IDs, separated by spaces, to a unique thread ID.  The IDs
8967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * come from the canonical_addresses table.  This works
8977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * because messages are considered to be part of the same
8987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * thread if they have the same subject (or a null subject)
8997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * and the same set of recipients.
9007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         */
9017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE threads (" +
9021ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                   Threads._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
9037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Threads.DATE + " INTEGER DEFAULT 0," +
9047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Threads.MESSAGE_COUNT + " INTEGER DEFAULT 0," +
9057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Threads.RECIPIENT_IDS + " TEXT," +
9067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Threads.SNIPPET + " TEXT," +
9077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Threads.SNIPPET_CHARSET + " INTEGER DEFAULT 0," +
9087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Threads.READ + " INTEGER DEFAULT 1," +
90982fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                   Threads.ARCHIVED + " INTEGER DEFAULT 0," +
9107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   Threads.TYPE + " INTEGER DEFAULT 0," +
9115f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                   Threads.ERROR + " INTEGER DEFAULT 0," +
9125f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                   Threads.HAS_ATTACHMENT + " INTEGER DEFAULT 0);");
9137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        /**
9157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         * This table stores the queue of messages to be sent/downloaded.
9167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project         */
9177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TABLE " + MmsSmsProvider.TABLE_PENDING_MSG +" (" +
9187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages._ID + " INTEGER PRIMARY KEY," +
9197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.PROTO_TYPE + " INTEGER," +
9207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.MSG_ID + " INTEGER," +
9217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.MSG_TYPE + " INTEGER," +
9227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.ERROR_TYPE + " INTEGER," +
9237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.ERROR_CODE + " INTEGER," +
9247236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.RETRY_INDEX + " INTEGER NOT NULL DEFAULT 0," +
9257236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.DUE_TIME + " INTEGER," +
926cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                   PendingMessages.SUB_ID + " INTEGER DEFAULT 0, " +
9277236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   PendingMessages.LAST_TRY + " INTEGER);");
9287236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9297236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
9307236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9317236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    // TODO Check the query plans for these triggers.
9327236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void createCommonTriggers(SQLiteDatabase db) {
9337236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Updates threads table whenever a message is added to sms.
9347236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER sms_update_thread_on_insert AFTER INSERT ON sms " +
9357236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE);
9367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Updates threads table whenever a message in sms is updated.
9387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER sms_update_thread_date_subject_on_update AFTER" +
9397236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE OF " + Sms.DATE + ", " + Sms.BODY + ", " + Sms.TYPE +
9407236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  ON sms " +
9417236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE);
9427236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Updates threads table whenever a message in sms is updated.
9447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER sms_update_thread_read_on_update AFTER" +
9457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE OF " + Sms.READ +
9467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  ON sms " +
9477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
9487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   SMS_UPDATE_THREAD_READ_BODY +
9497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
9507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
951527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        // As of DATABASE_VERSION 55, we've removed these triggers that delete empty threads.
952527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        // These triggers interfere with saving drafts on brand new threads. Instead of
953527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        // triggers cleaning up empty threads, the empty threads should be cleaned up by
954527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        // an explicit call to delete with Threads.OBSOLETE_THREADS_URI.
955527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor
956527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//        // When the last message in a thread is deleted, these
957527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//        // triggers ensure that the entry for its thread ID is removed
958527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//        // from the threads table.
959527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//        db.execSQL("CREATE TRIGGER delete_obsolete_threads_pdu " +
960527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "AFTER DELETE ON pdu " +
961527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "BEGIN " +
962527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "  DELETE FROM threads " +
963527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "  WHERE " +
964527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "    _id = old.thread_id " +
965527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "    AND _id NOT IN " +
966527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "    (SELECT thread_id FROM sms " +
967527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "     UNION SELECT thread_id from pdu); " +
968527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "END;");
969527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//
970527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//        db.execSQL("CREATE TRIGGER delete_obsolete_threads_when_update_pdu " +
971527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "AFTER UPDATE OF " + Mms.THREAD_ID + " ON pdu " +
972527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "WHEN old." + Mms.THREAD_ID + " != new." + Mms.THREAD_ID + " " +
973527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "BEGIN " +
974527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "  DELETE FROM threads " +
975527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "  WHERE " +
976527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "    _id = old.thread_id " +
977527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "    AND _id NOT IN " +
978527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "    (SELECT thread_id FROM sms " +
979527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "     UNION SELECT thread_id from pdu); " +
980527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor//                   "END;");
9817236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9827236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // TODO Add triggers for SMS retry-status management.
9837236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
9847236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Update the error flag of threads when the error type of
9857236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // a pending MM is updated.
9867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER update_threads_error_on_update_mms " +
9877236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  AFTER UPDATE OF err_type ON pending_msgs " +
9887236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHEN (OLD.err_type < 10 AND NEW.err_type >= 10)" +
9897236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    OR (OLD.err_type >= 10 AND NEW.err_type < 10) " +
9907236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN" +
9917236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE threads SET error = " +
9927236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    CASE" +
9937236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "      WHEN NEW.err_type >= 10 THEN error + 1" +
9947236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "      ELSE error - 1" +
9957236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    END " +
9967236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHERE _id =" +
9977236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "   (SELECT DISTINCT thread_id" +
9987236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    FROM pdu" +
9997236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    WHERE _id = NEW.msg_id); " +
10007236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
10017236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
10027236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // Update the error flag of threads after a text message was
10037236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        // failed to send/receive.
10047236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER update_threads_error_on_update_sms " +
10057236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  AFTER UPDATE OF type ON sms" +
10067236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHEN (OLD.type != 5 AND NEW.type = 5)" +
10077236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    OR (OLD.type = 5 AND NEW.type != 5) " +
10087236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
10097236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE threads SET error = " +
10107236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    CASE" +
10117236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "      WHEN NEW.type = 5 THEN error + 1" +
10127236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "      ELSE error - 1" +
10137236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "    END " +
10147236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHERE _id = NEW.thread_id; " +
10157236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
10167236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
10177236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
10187236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    @Override
10197236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
10207236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        Log.w(TAG, "Upgrading database from version " + oldVersion
10217236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                + " to " + currentVersion + ".");
10227236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
10237236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        switch (oldVersion) {
10245f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        case 40:
10255f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            if (currentVersion <= 40) {
10265f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                return;
10275f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            }
10285f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project
10295f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            db.beginTransaction();
10305f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            try {
10315f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                upgradeDatabaseToVersion41(db);
10325f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                db.setTransactionSuccessful();
10335f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            } catch (Throwable ex) {
10345f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                Log.e(TAG, ex.getMessage(), ex);
10355f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                break;
10365f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            } finally {
10375f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                db.endTransaction();
10385f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            }
10395f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            // fall through
10405f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        case 41:
10415f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            if (currentVersion <= 41) {
10425f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                return;
10435f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            }
1044f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
10455f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            db.beginTransaction();
10465f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            try {
10475f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                upgradeDatabaseToVersion42(db);
10485f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                db.setTransactionSuccessful();
10495f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            } catch (Throwable ex) {
10505f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                Log.e(TAG, ex.getMessage(), ex);
10515f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                break;
10525f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            } finally {
10535f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                db.endTransaction();
10545f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            }
10555f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            // fall through
10565f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        case 42:
10575f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            if (currentVersion <= 42) {
10587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                return;
10595f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            }
1060f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
10615f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            db.beginTransaction();
10625f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            try {
10635f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                upgradeDatabaseToVersion43(db);
10645f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                db.setTransactionSuccessful();
10655f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            } catch (Throwable ex) {
10665f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                Log.e(TAG, ex.getMessage(), ex);
10675f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                break;
10685f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            } finally {
10695f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project                db.endTransaction();
10705f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project            }
10712ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            // fall through
10722ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang        case 43:
10732ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            if (currentVersion <= 43) {
10742ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                return;
10752ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            }
10762ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang
10772ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            db.beginTransaction();
10782ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            try {
10792ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                upgradeDatabaseToVersion44(db);
10802ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                db.setTransactionSuccessful();
10812ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            } catch (Throwable ex) {
10822ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                Log.e(TAG, ex.getMessage(), ex);
10832ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                break;
10842ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            } finally {
10852ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang                db.endTransaction();
10862ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang            }
1087ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            // fall through
1088a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor        case 44:
1089a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor            if (currentVersion <= 44) {
1090a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                return;
1091a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor            }
1092a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor
1093a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor            db.beginTransaction();
1094a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor            try {
1095a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                upgradeDatabaseToVersion45(db);
1096a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                db.setTransactionSuccessful();
1097a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor            } catch (Throwable ex) {
1098a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                Log.e(TAG, ex.getMessage(), ex);
1099a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                break;
1100a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor            } finally {
1101a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor                db.endTransaction();
1102a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor            }
1103ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            // fall through
1104f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        case 45:
1105f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            if (currentVersion <= 45) {
1106f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                return;
1107f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            }
1108f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            db.beginTransaction();
1109f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            try {
1110f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                upgradeDatabaseToVersion46(db);
1111f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                db.setTransactionSuccessful();
1112f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            } catch (Throwable ex) {
1113f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                Log.e(TAG, ex.getMessage(), ex);
1114f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                break;
1115f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            } finally {
1116f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                db.endTransaction();
1117f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            }
11181047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            // fall through
11191047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        case 46:
11201047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            if (currentVersion <= 46) {
11211047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                return;
11221047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            }
11231047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang
11241047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            db.beginTransaction();
11251047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            try {
11261047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                upgradeDatabaseToVersion47(db);
11271047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                db.setTransactionSuccessful();
11281047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            } catch (Throwable ex) {
11291047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                Log.e(TAG, ex.getMessage(), ex);
11301047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                break;
11311047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            } finally {
11321047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                db.endTransaction();
11331047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang            }
1134ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            // fall through
1135ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor        case 47:
1136ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            if (currentVersion <= 47) {
1137ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor                return;
1138ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            }
1139ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor
1140ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            db.beginTransaction();
1141ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            try {
1142ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor                upgradeDatabaseToVersion48(db);
1143ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor                db.setTransactionSuccessful();
1144ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            } catch (Throwable ex) {
1145ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor                Log.e(TAG, ex.getMessage(), ex);
1146ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor                break;
1147ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            } finally {
1148ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor                db.endTransaction();
1149ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor            }
1150dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            // fall through
11518e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner        case 48:
11528e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            if (currentVersion <= 48) {
11538e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                return;
11548e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            }
11558e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner
11568e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            db.beginTransaction();
11578e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            try {
11587ad939ed205080002ab32d318414337fc9c3ce1fTom Taylor                createWordsTables(db);
11598e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                db.setTransactionSuccessful();
11608e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            } catch (Throwable ex) {
11618e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                Log.e(TAG, ex.getMessage(), ex);
11628e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                break;
11638e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            } finally {
11648e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner                db.endTransaction();
11658e5ee782690175e9cfb9a37f600f207b952ba8a6Mark Wagner            }
1166dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            // fall through
1167a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor        case 49:
1168a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            if (currentVersion <= 49) {
1169a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor                return;
1170a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            }
1171a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            db.beginTransaction();
1172a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            try {
1173a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor                createThreadIdIndex(db);
1174a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor                db.setTransactionSuccessful();
1175a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            } catch (Throwable ex) {
1176a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor                Log.e(TAG, ex.getMessage(), ex);
1177a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor                break; // force to destroy all old data;
1178a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            } finally {
1179a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor                db.endTransaction();
1180a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor            }
1181dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            // fall through
1182dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang        case 50:
1183dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            if (currentVersion <= 50) {
1184dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                return;
1185dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            }
11867236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
1187dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            db.beginTransaction();
1188dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            try {
1189dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                upgradeDatabaseToVersion51(db);
1190dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                db.setTransactionSuccessful();
1191dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            } catch (Throwable ex) {
1192dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                Log.e(TAG, ex.getMessage(), ex);
1193dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                break;
1194dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            } finally {
1195dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang                db.endTransaction();
1196dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            }
1197fc0eb2f2905477c7200eb54584d2c104cd6d1adbTom Taylor            // fall through
1198fc0eb2f2905477c7200eb54584d2c104cd6d1adbTom Taylor        case 51:
1199fc0eb2f2905477c7200eb54584d2c104cd6d1adbTom Taylor            if (currentVersion <= 51) {
1200fc0eb2f2905477c7200eb54584d2c104cd6d1adbTom Taylor                return;
1201fc0eb2f2905477c7200eb54584d2c104cd6d1adbTom Taylor            }
12028a4060ec0c2433ceeb619a3a35fba5aabedbc1c6Tom Taylor            // 52 was adding a new meta_data column, but that was removed.
1203fc0eb2f2905477c7200eb54584d2c104cd6d1adbTom Taylor            // fall through
12041e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor        case 52:
12051e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor            if (currentVersion <= 52) {
12061e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                return;
12071e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor            }
1208dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang
12091e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor            db.beginTransaction();
12101e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor            try {
12111e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                upgradeDatabaseToVersion53(db);
12121e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                db.setTransactionSuccessful();
12131e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor            } catch (Throwable ex) {
12141e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                Log.e(TAG, ex.getMessage(), ex);
12151e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                break;
12161e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor            } finally {
12171e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor                db.endTransaction();
12181e47c4888938f8abbe581707b8762d49c12b9b7aTom Taylor            }
1219ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            // fall through
1220ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        case 53:
1221ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            if (currentVersion <= 53) {
1222ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                return;
1223ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            }
1224ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert
1225ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            db.beginTransaction();
1226ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            try {
1227ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                upgradeDatabaseToVersion54(db);
1228ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                db.setTransactionSuccessful();
1229ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            } catch (Throwable ex) {
1230ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                Log.e(TAG, ex.getMessage(), ex);
1231ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                break;
1232ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            } finally {
1233ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                db.endTransaction();
1234ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert            }
1235527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            // fall through
1236527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        case 54:
1237527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            if (currentVersion <= 54) {
1238527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor                return;
1239527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            }
1240527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor
1241527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            db.beginTransaction();
1242527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            try {
1243527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor                upgradeDatabaseToVersion55(db);
1244527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor                db.setTransactionSuccessful();
1245527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            } catch (Throwable ex) {
1246527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor                Log.e(TAG, ex.getMessage(), ex);
1247527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor                break;
1248527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            } finally {
1249527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor                db.endTransaction();
1250527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor            }
1251f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor            // fall through
1252f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor        case 55:
1253f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor            if (currentVersion <= 55) {
1254f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor                return;
1255f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor            }
1256f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor
1257f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor            db.beginTransaction();
1258f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor            try {
1259f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor                upgradeDatabaseToVersion56(db);
1260f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor                db.setTransactionSuccessful();
1261f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor            } catch (Throwable ex) {
1262f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor                Log.e(TAG, ex.getMessage(), ex);
1263f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor                break;
1264f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor            } finally {
1265f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor                db.endTransaction();
1266f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor            }
12671a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor            // fall through
12681a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor        case 56:
12691a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor            if (currentVersion <= 56) {
12701a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor                return;
12711a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor            }
12721a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor
12731a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor            db.beginTransaction();
12741a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor            try {
12751a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor                upgradeDatabaseToVersion57(db);
12761a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor                db.setTransactionSuccessful();
12771a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor            } catch (Throwable ex) {
12781a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor                Log.e(TAG, ex.getMessage(), ex);
12791a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor                break;
12801a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor            } finally {
12811a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor                db.endTransaction();
12821a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor            }
1283cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen            // fall through
1284cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen        case 57:
1285cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen            if (currentVersion <= 57) {
1286cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                return;
1287cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen            }
1288cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen
1289cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen            db.beginTransaction();
1290cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen            try {
1291cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                upgradeDatabaseToVersion58(db);
1292cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                db.setTransactionSuccessful();
1293cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen            } catch (Throwable ex) {
1294cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                Log.e(TAG, ex.getMessage(), ex);
1295cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                break;
1296cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen            } finally {
1297cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                db.endTransaction();
1298cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen            }
129949776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen            // fall through
130049776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen        case 58:
130149776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen            if (currentVersion <= 58) {
130249776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen                return;
130349776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen            }
130449776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen
130549776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen            db.beginTransaction();
130649776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen            try {
130749776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen                upgradeDatabaseToVersion59(db);
130849776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen                db.setTransactionSuccessful();
130949776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen            } catch (Throwable ex) {
131049776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen                Log.e(TAG, ex.getMessage(), ex);
131149776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen                break;
131249776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen            } finally {
131349776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen                db.endTransaction();
131449776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen            }
131582fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen            // fall through
131682fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen        case 59:
131782fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen            if (currentVersion <= 59) {
131882fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                return;
131982fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen            }
132082fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen
132182fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen            db.beginTransaction();
132282fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen            try {
132382fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                upgradeDatabaseToVersion60(db);
132482fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                db.setTransactionSuccessful();
132582fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen            } catch (Throwable ex) {
132682fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                Log.e(TAG, ex.getMessage(), ex);
132782fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                break;
132882fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen            } finally {
132982fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                db.endTransaction();
133082fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen            }
1331dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang            return;
1332a6e44cb0cc7866439acba48ea18bdac9862afbdeTom Taylor        }
1333f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
13345f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        Log.e(TAG, "Destroying all old data.");
13355f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        dropAll(db);
13367236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        onCreate(db);
13377236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
13387236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
13395f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    private void dropAll(SQLiteDatabase db) {
13405f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        // Clean the database out in order to start over from scratch.
13415f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        // We don't need to drop our triggers here because SQLite automatically
13425f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        // drops a trigger when its attached database is dropped.
13437236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS canonical_addresses");
13447236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS threads");
13457236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS " + MmsSmsProvider.TABLE_PENDING_MSG);
13467236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS sms");
13477236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS raw");
13487236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS attachments");
13497236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS thread_ids");
13507236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS sr_pending");
13517236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_PDU + ";");
13527236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_ADDR + ";");
13537236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_PART + ";");
13547236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_RATE + ";");
13557236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TABLE IF EXISTS " + MmsProvider.TABLE_DRM + ";");
13567236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
13577236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project
13587236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void upgradeDatabaseToVersion41(SQLiteDatabase db) {
13597236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TRIGGER IF EXISTS update_threads_error_on_move_mms");
13607236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("CREATE TRIGGER update_threads_error_on_move_mms " +
13617236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  BEFORE UPDATE OF msg_box ON pdu " +
13627236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHEN (OLD.msg_box = 4 AND NEW.msg_box != 4) " +
13637236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  AND (OLD._id IN (SELECT DISTINCT msg_id" +
13647236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "                   FROM pending_msgs" +
13657236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "                   WHERE err_type >= 10)) " +
13667236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "BEGIN " +
13677236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  UPDATE threads SET error = error - 1" +
13687236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "  WHERE _id = OLD.thread_id; " +
13697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project                   "END;");
13707236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
1371f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
13727236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    private void upgradeDatabaseToVersion42(SQLiteDatabase db) {
13737236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TRIGGER IF EXISTS sms_update_thread_on_delete");
13747236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TRIGGER IF EXISTS delete_obsolete_threads_sms");
13757236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project        db.execSQL("DROP TRIGGER IF EXISTS update_threads_error_on_delete_sms");
13767236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project    }
1377f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
13785f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    private void upgradeDatabaseToVersion43(SQLiteDatabase db) {
13795f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        // Add 'has_attachment' column to threads table.
13805f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        db.execSQL("ALTER TABLE threads ADD COLUMN has_attachment INTEGER DEFAULT 0");
13815f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project
13821047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        updateThreadsAttachmentColumn(db);
13835f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project
13845f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        // Add insert and delete triggers for keeping it up to date.
13855f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        db.execSQL(PART_UPDATE_THREADS_ON_INSERT_TRIGGER);
13865f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project        db.execSQL(PART_UPDATE_THREADS_ON_DELETE_TRIGGER);
13875f1e43fe6163014d8c56325daf7af364c2ff077fThe Android Open Source Project    }
13882ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang
13892ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang    private void upgradeDatabaseToVersion44(SQLiteDatabase db) {
13901047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        updateThreadsAttachmentColumn(db);
13912ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang
13922ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang        // add the update trigger for keeping the threads up to date.
13932ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang        db.execSQL(PART_UPDATE_THREADS_ON_UPDATE_TRIGGER);
13942ad5ba8b1fc7b9197b78a9c3a0039522bdbd402fWei Huang    }
1395a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor
1396a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor    private void upgradeDatabaseToVersion45(SQLiteDatabase db) {
1397a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor        // Add 'locked' column to sms table.
1398fc0eb2f2905477c7200eb54584d2c104cd6d1adbTom Taylor        db.execSQL("ALTER TABLE sms ADD COLUMN " + Sms.LOCKED + " INTEGER DEFAULT 0");
1399a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor
1400a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor        // Add 'locked' column to pdu table.
1401a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor        db.execSQL("ALTER TABLE pdu ADD COLUMN " + Mms.LOCKED + " INTEGER DEFAULT 0");
1402a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor    }
1403a48a9665519f98d1e89b24d17726d7a478e575f2Tom Taylor
1404f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner    private void upgradeDatabaseToVersion46(SQLiteDatabase db) {
1405f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        // add the "text" column for caching inline text (e.g. strings) instead of
1406f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        // putting them in an external file
1407f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        db.execSQL("ALTER TABLE part ADD COLUMN " + Part.TEXT + " TEXT");
1408f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
1409f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        Cursor textRows = db.query(
1410f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                "part",
1411f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                new String[] { Part._ID, Part._DATA, Part.TEXT},
1412f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                "ct = 'text/plain' OR ct == 'application/smil'",
1413f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                null,
1414f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                null,
1415f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                null,
1416f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                null);
1417f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        ArrayList<String> filesToDelete = new ArrayList<String>();
1418f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        try {
14190ebbb48f9f83ad65d738d1910a38e4fbdb920ac7Jeff Hamilton            db.beginTransaction();
1420f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            if (textRows != null) {
1421f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                int partDataColumn = textRows.getColumnIndex(Part._DATA);
1422f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner
1423f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                // This code is imperfect in that we can't guarantee that all the
1424f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                // backing files get deleted.  For example if the system aborts after
1425f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                // the database is updated but before we complete the process of
1426f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                // deleting files.
1427f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                while (textRows.moveToNext()) {
1428f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                    String path = textRows.getString(partDataColumn);
1429f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                    if (path != null) {
1430f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                        try {
1431f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            InputStream is = new FileInputStream(path);
1432f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            byte [] data = new byte[is.available()];
1433f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            is.read(data);
1434f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            EncodedStringValue v = new EncodedStringValue(data);
14350ebbb48f9f83ad65d738d1910a38e4fbdb920ac7Jeff Hamilton                            db.execSQL("UPDATE part SET " + Part._DATA + " = NULL, " +
14360ebbb48f9f83ad65d738d1910a38e4fbdb920ac7Jeff Hamilton                                    Part.TEXT + " = ?", new String[] { v.getString() });
1437f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            is.close();
1438f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            filesToDelete.add(path);
1439f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                        } catch (IOException e) {
1440f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            // TODO Auto-generated catch block
1441f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                            e.printStackTrace();
1442f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                        }
1443f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                    }
1444f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                }
1445f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            }
14460ebbb48f9f83ad65d738d1910a38e4fbdb920ac7Jeff Hamilton            db.setTransactionSuccessful();
1447f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        } finally {
14480ebbb48f9f83ad65d738d1910a38e4fbdb920ac7Jeff Hamilton            db.endTransaction();
1449f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            for (String pathToDelete : filesToDelete) {
1450f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                try {
1451f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                    (new File(pathToDelete)).delete();
1452f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                } catch (SecurityException ex) {
1453f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                    Log.e(TAG, "unable to clean up old mms file for " + pathToDelete, ex);
1454f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                }
1455f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            }
1456f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            if (textRows != null) {
1457f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner                textRows.close();
1458f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner            }
1459f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner        }
1460f0a9e90721310bed023a9ff1f176f1b5e05a14f7Mark Wagner    }
14611047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang
14621047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang    private void upgradeDatabaseToVersion47(SQLiteDatabase db) {
14631047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        updateThreadsAttachmentColumn(db);
14641047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang
14651047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        // add the update trigger for keeping the threads up to date.
14661047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        db.execSQL(PDU_UPDATE_THREADS_ON_UPDATE_TRIGGER);
14671047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang    }
14681047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang
1469ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor    private void upgradeDatabaseToVersion48(SQLiteDatabase db) {
1470ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor        // Add 'error_code' column to sms table.
1471ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor        db.execSQL("ALTER TABLE sms ADD COLUMN error_code INTEGER DEFAULT 0");
1472ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor    }
1473ddf267c20a697f66b8238538fb6ad31507724692Tom Taylor
1474dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang    private void upgradeDatabaseToVersion51(SQLiteDatabase db) {
1475dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang        db.execSQL("ALTER TABLE sms add COLUMN seen INTEGER DEFAULT 0");
1476dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang        db.execSQL("ALTER TABLE pdu add COLUMN seen INTEGER DEFAULT 0");
1477a882662df39eb5af84cc386fc09df4636166f48fWei Huang
1478a882662df39eb5af84cc386fc09df4636166f48fWei Huang        try {
1479a882662df39eb5af84cc386fc09df4636166f48fWei Huang            // update the existing sms and pdu tables so the new "seen" column is the same as
1480a882662df39eb5af84cc386fc09df4636166f48fWei Huang            // the "read" column for each row.
1481a882662df39eb5af84cc386fc09df4636166f48fWei Huang            ContentValues contentValues = new ContentValues();
1482a882662df39eb5af84cc386fc09df4636166f48fWei Huang            contentValues.put("seen", 1);
1483a882662df39eb5af84cc386fc09df4636166f48fWei Huang            int count = db.update("sms", contentValues, "read=1", null);
1484a882662df39eb5af84cc386fc09df4636166f48fWei Huang            Log.d(TAG, "[MmsSmsDb] upgradeDatabaseToVersion51: updated " + count +
1485a882662df39eb5af84cc386fc09df4636166f48fWei Huang                    " rows in sms table to have READ=1");
1486a882662df39eb5af84cc386fc09df4636166f48fWei Huang            count = db.update("pdu", contentValues, "read=1", null);
1487a882662df39eb5af84cc386fc09df4636166f48fWei Huang            Log.d(TAG, "[MmsSmsDb] upgradeDatabaseToVersion51: updated " + count +
1488a882662df39eb5af84cc386fc09df4636166f48fWei Huang                    " rows in pdu table to have READ=1");
1489a882662df39eb5af84cc386fc09df4636166f48fWei Huang        } catch (Exception ex) {
1490a882662df39eb5af84cc386fc09df4636166f48fWei Huang            Log.e(TAG, "[MmsSmsDb] upgradeDatabaseToVersion51 caught ", ex);
1491a882662df39eb5af84cc386fc09df4636166f48fWei Huang        }
1492dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang    }
1493dfac57630db2993a1cda15ee4fb697ea1baadb0bWei Huang
1494ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert    private void upgradeDatabaseToVersion53(SQLiteDatabase db) {
1495ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        db.execSQL("DROP TRIGGER IF EXISTS pdu_update_thread_read_on_update");
1496ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert
1497ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        // Updates threads table whenever a message in pdu is updated.
1498ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        db.execSQL("CREATE TRIGGER pdu_update_thread_read_on_update AFTER" +
1499ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   "  UPDATE OF " + Mms.READ +
1500ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   "  ON " + MmsProvider.TABLE_PDU + " " +
1501ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   PDU_UPDATE_THREAD_CONSTRAINTS +
1502ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   "BEGIN " +
1503ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   PDU_UPDATE_THREAD_READ_BODY +
1504ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert                   "END;");
1505ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert    }
1506ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert
1507ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert    private void upgradeDatabaseToVersion54(SQLiteDatabase db) {
1508ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        // Add 'date_sent' column to sms table.
1509ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        db.execSQL("ALTER TABLE sms ADD COLUMN " + Sms.DATE_SENT + " INTEGER DEFAULT 0");
1510ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert
1511ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        // Add 'date_sent' column to pdu table.
1512ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert        db.execSQL("ALTER TABLE pdu ADD COLUMN " + Mms.DATE_SENT + " INTEGER DEFAULT 0");
1513ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert    }
1514ea5c40c18a83bd984da79ecda301bd5a7cd9daa1Fredrik Roubert
1515527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor    private void upgradeDatabaseToVersion55(SQLiteDatabase db) {
1516527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        // Drop removed triggers
1517527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS delete_obsolete_threads_pdu");
1518527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor        db.execSQL("DROP TRIGGER IF EXISTS delete_obsolete_threads_when_update_pdu");
1519527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor    }
1520527fcced9fe9cf8525e33ffb098fd28650af24afTom Taylor
1521f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor    private void upgradeDatabaseToVersion56(SQLiteDatabase db) {
1522f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor        // Add 'text_only' column to pdu table.
1523f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor        db.execSQL("ALTER TABLE " + MmsProvider.TABLE_PDU + " ADD COLUMN " + Mms.TEXT_ONLY +
1524f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor                " INTEGER DEFAULT 0");
1525f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor    }
1526f88d1d6733158144e9e0c87f29b446068edf0507Tom Taylor
15271a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor    private void upgradeDatabaseToVersion57(SQLiteDatabase db) {
15281a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor        // Clear out bad rows, those with empty threadIds, from the pdu table.
15291a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor        db.execSQL("DELETE FROM " + MmsProvider.TABLE_PDU + " WHERE " + Mms.THREAD_ID + " IS NULL");
15301a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor    }
15311a45ce5c6e417fee13c55221a97c3d36b4bea846Tom Taylor
1532cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen    private void upgradeDatabaseToVersion58(SQLiteDatabase db) {
1533cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen        db.execSQL("ALTER TABLE " + MmsProvider.TABLE_PDU +" ADD COLUMN "
1534cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                + Mms.SUB_ID + " INTEGER DEFAULT -1");
1535cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen        db.execSQL("ALTER TABLE " + MmsSmsProvider.TABLE_PENDING_MSG +" ADD COLUMN "
1536cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                + "pending_sub_id" + " INTEGER DEFAULT 0");
1537cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen        db.execSQL("ALTER TABLE " + SmsProvider.TABLE_SMS +" ADD COLUMN "
1538cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                + Sms.SUB_ID + " INTEGER DEFAULT -1");
1539cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen        db.execSQL("ALTER TABLE " + SmsProvider.TABLE_RAW +" ADD COLUMN "
1540cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                + Sms.SUB_ID + " INTEGER DEFAULT -1");
1541cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen    }
1542cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen
154349776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen    private void upgradeDatabaseToVersion59(SQLiteDatabase db) {
154449776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen        db.execSQL("ALTER TABLE " + MmsProvider.TABLE_PDU +" ADD COLUMN "
154549776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen                + Mms.CREATOR + " TEXT");
154649776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen        db.execSQL("ALTER TABLE " + SmsProvider.TABLE_SMS +" ADD COLUMN "
154749776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen                + Sms.CREATOR + " TEXT");
154849776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen    }
154949776410646ba3eb7aef3ec34871a38aa69441c4Ye Wen
155082fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen    private void upgradeDatabaseToVersion60(SQLiteDatabase db) {
155182fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen        db.execSQL("ALTER TABLE " + MmsSmsProvider.TABLE_THREADS +" ADD COLUMN "
155282fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen                + Threads.ARCHIVED + " INTEGER DEFAULT 0");
155382fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen    }
155482fc72b94a54eb3c70bcfbb1effd9b3a9b775af9Ye Wen
15551ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    @Override
15561ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    public synchronized SQLiteDatabase getWritableDatabase() {
15571ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        SQLiteDatabase db = super.getWritableDatabase();
15581ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor
155910faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        if (!sTriedAutoIncrement) {
156010faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor            sTriedAutoIncrement = true;
156115156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor            boolean hasAutoIncrementThreads = hasAutoIncrement(db, MmsSmsProvider.TABLE_THREADS);
156209710cec4926bcd3708376face04507e661bcc02Tom Taylor            boolean hasAutoIncrementAddresses = hasAutoIncrement(db, "canonical_addresses");
156349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor            boolean hasAutoIncrementPart = hasAutoIncrement(db, "part");
156449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor            boolean hasAutoIncrementPdu = hasAutoIncrement(db, "pdu");
156509710cec4926bcd3708376face04507e661bcc02Tom Taylor            Log.d(TAG, "[getWritableDatabase] hasAutoIncrementThreads: " + hasAutoIncrementThreads +
156649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    " hasAutoIncrementAddresses: " + hasAutoIncrementAddresses +
156749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    " hasAutoIncrementPart: " + hasAutoIncrementPart +
156849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    " hasAutoIncrementPdu: " + hasAutoIncrementPdu);
156909710cec4926bcd3708376face04507e661bcc02Tom Taylor            boolean autoIncrementThreadsSuccess = true;
157009710cec4926bcd3708376face04507e661bcc02Tom Taylor            boolean autoIncrementAddressesSuccess = true;
157149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor            boolean autoIncrementPartSuccess = true;
157249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor            boolean autoIncrementPduSuccess = true;
157309710cec4926bcd3708376face04507e661bcc02Tom Taylor            if (!hasAutoIncrementThreads) {
15741ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                db.beginTransaction();
15751ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                try {
157610faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor                    if (false && sFakeLowStorageTest) {
157710faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor                        Log.d(TAG, "[getWritableDatabase] mFakeLowStorageTest is true " +
157810faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor                                " - fake exception");
157910faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor                        throw new Exception("FakeLowStorageTest");
158010faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor                    }
158109710cec4926bcd3708376face04507e661bcc02Tom Taylor                    upgradeThreadsTableToAutoIncrement(db);     // a no-op if already upgraded
15821ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                    db.setTransactionSuccessful();
15831ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                } catch (Throwable ex) {
158409710cec4926bcd3708376face04507e661bcc02Tom Taylor                    Log.e(TAG, "Failed to add autoIncrement to threads;: " + ex.getMessage(), ex);
158509710cec4926bcd3708376face04507e661bcc02Tom Taylor                    autoIncrementThreadsSuccess = false;
158609710cec4926bcd3708376face04507e661bcc02Tom Taylor                } finally {
158709710cec4926bcd3708376face04507e661bcc02Tom Taylor                    db.endTransaction();
158809710cec4926bcd3708376face04507e661bcc02Tom Taylor                }
158909710cec4926bcd3708376face04507e661bcc02Tom Taylor            }
159009710cec4926bcd3708376face04507e661bcc02Tom Taylor            if (!hasAutoIncrementAddresses) {
159109710cec4926bcd3708376face04507e661bcc02Tom Taylor                db.beginTransaction();
159209710cec4926bcd3708376face04507e661bcc02Tom Taylor                try {
159309710cec4926bcd3708376face04507e661bcc02Tom Taylor                    if (false && sFakeLowStorageTest) {
159409710cec4926bcd3708376face04507e661bcc02Tom Taylor                        Log.d(TAG, "[getWritableDatabase] mFakeLowStorageTest is true " +
159509710cec4926bcd3708376face04507e661bcc02Tom Taylor                        " - fake exception");
159609710cec4926bcd3708376face04507e661bcc02Tom Taylor                        throw new Exception("FakeLowStorageTest");
159710faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor                    }
159809710cec4926bcd3708376face04507e661bcc02Tom Taylor                    upgradeAddressTableToAutoIncrement(db);     // a no-op if already upgraded
159909710cec4926bcd3708376face04507e661bcc02Tom Taylor                    db.setTransactionSuccessful();
160009710cec4926bcd3708376face04507e661bcc02Tom Taylor                } catch (Throwable ex) {
160109710cec4926bcd3708376face04507e661bcc02Tom Taylor                    Log.e(TAG, "Failed to add autoIncrement to canonical_addresses: " +
160209710cec4926bcd3708376face04507e661bcc02Tom Taylor                            ex.getMessage(), ex);
160309710cec4926bcd3708376face04507e661bcc02Tom Taylor                    autoIncrementAddressesSuccess = false;
16041ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                } finally {
16051ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                    db.endTransaction();
16061ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                }
16071ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor            }
160849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor            if (!hasAutoIncrementPart) {
160949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                db.beginTransaction();
161049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                try {
161149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    if (false && sFakeLowStorageTest) {
161249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                        Log.d(TAG, "[getWritableDatabase] mFakeLowStorageTest is true " +
161349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                        " - fake exception");
161449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                        throw new Exception("FakeLowStorageTest");
161549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    }
161649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    upgradePartTableToAutoIncrement(db);     // a no-op if already upgraded
161749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    db.setTransactionSuccessful();
161849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                } catch (Throwable ex) {
161949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    Log.e(TAG, "Failed to add autoIncrement to part: " +
162049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                            ex.getMessage(), ex);
162149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    autoIncrementPartSuccess = false;
162249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                } finally {
162349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    db.endTransaction();
162449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                }
162549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor            }
162649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor            if (!hasAutoIncrementPdu) {
162749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                db.beginTransaction();
162849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                try {
162949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    if (false && sFakeLowStorageTest) {
163049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                        Log.d(TAG, "[getWritableDatabase] mFakeLowStorageTest is true " +
163149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                        " - fake exception");
163249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                        throw new Exception("FakeLowStorageTest");
163349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    }
163449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    upgradePduTableToAutoIncrement(db);     // a no-op if already upgraded
163549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    db.setTransactionSuccessful();
163649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                } catch (Throwable ex) {
163749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    Log.e(TAG, "Failed to add autoIncrement to pdu: " +
163849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                            ex.getMessage(), ex);
163949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    autoIncrementPduSuccess = false;
164049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                } finally {
164149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    db.endTransaction();
164249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                }
164349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor            }
164449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor            if (autoIncrementThreadsSuccess &&
164549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    autoIncrementAddressesSuccess &&
164649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    autoIncrementPartSuccess &&
164749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                    autoIncrementPduSuccess) {
164809710cec4926bcd3708376face04507e661bcc02Tom Taylor                if (mLowStorageMonitor != null) {
164909710cec4926bcd3708376face04507e661bcc02Tom Taylor                    // We've already updated the database. This receiver is no longer necessary.
165009710cec4926bcd3708376face04507e661bcc02Tom Taylor                    Log.d(TAG, "Unregistering mLowStorageMonitor - we've upgraded");
165109710cec4926bcd3708376face04507e661bcc02Tom Taylor                    mContext.unregisterReceiver(mLowStorageMonitor);
165209710cec4926bcd3708376face04507e661bcc02Tom Taylor                    mLowStorageMonitor = null;
165309710cec4926bcd3708376face04507e661bcc02Tom Taylor                }
165409710cec4926bcd3708376face04507e661bcc02Tom Taylor            } else {
165509710cec4926bcd3708376face04507e661bcc02Tom Taylor                if (sFakeLowStorageTest) {
165609710cec4926bcd3708376face04507e661bcc02Tom Taylor                    sFakeLowStorageTest = false;
165709710cec4926bcd3708376face04507e661bcc02Tom Taylor                }
165809710cec4926bcd3708376face04507e661bcc02Tom Taylor
165909710cec4926bcd3708376face04507e661bcc02Tom Taylor                // We failed, perhaps because of low storage. Turn on a receiver to watch for
166009710cec4926bcd3708376face04507e661bcc02Tom Taylor                // storage space.
166109710cec4926bcd3708376face04507e661bcc02Tom Taylor                if (mLowStorageMonitor == null) {
166209710cec4926bcd3708376face04507e661bcc02Tom Taylor                    Log.d(TAG, "[getWritableDatabase] turning on storage monitor");
166309710cec4926bcd3708376face04507e661bcc02Tom Taylor                    mLowStorageMonitor = new LowStorageMonitor();
166409710cec4926bcd3708376face04507e661bcc02Tom Taylor                    IntentFilter intentFilter = new IntentFilter();
166509710cec4926bcd3708376face04507e661bcc02Tom Taylor                    intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_LOW);
166609710cec4926bcd3708376face04507e661bcc02Tom Taylor                    intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
166709710cec4926bcd3708376face04507e661bcc02Tom Taylor                    mContext.registerReceiver(mLowStorageMonitor, intentFilter);
166809710cec4926bcd3708376face04507e661bcc02Tom Taylor                }
166909710cec4926bcd3708376face04507e661bcc02Tom Taylor            }
16701ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        }
16711ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        return db;
16721ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    }
16731ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor
167409710cec4926bcd3708376face04507e661bcc02Tom Taylor    // Determine whether a particular table has AUTOINCREMENT in its schema.
167509710cec4926bcd3708376face04507e661bcc02Tom Taylor    private boolean hasAutoIncrement(SQLiteDatabase db, String tableName) {
16761ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        boolean result = false;
167709710cec4926bcd3708376face04507e661bcc02Tom Taylor        String query = "SELECT sql FROM sqlite_master WHERE type='table' AND name='" +
167809710cec4926bcd3708376face04507e661bcc02Tom Taylor                        tableName + "'";
16791ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        Cursor c = db.rawQuery(query, null);
16801ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        if (c != null) {
16811ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor            try {
16821ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                if (c.moveToFirst()) {
16831ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                    String schema = c.getString(0);
16841ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                    result = schema != null ? schema.contains("AUTOINCREMENT") : false;
168509710cec4926bcd3708376face04507e661bcc02Tom Taylor                    Log.d(TAG, "[MmsSmsDb] tableName: " + tableName + " hasAutoIncrement: " +
168609710cec4926bcd3708376face04507e661bcc02Tom Taylor                            schema + " result: " + result);
16871ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                }
16881ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor            } finally {
16891ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                c.close();
16901ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor            }
16911ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        }
16921ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        return result;
16931ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    }
16941ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor
16951ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    // upgradeThreadsTableToAutoIncrement() is called to add the AUTOINCREMENT keyword to
16961ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    // the threads table. This could fail if the user has a lot of conversations and not enough
16971ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    // storage to make a copy of the threads table. That's ok. This upgrade is optional. It'll
16981ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    // be called again next time the device is rebooted.
16991ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    private void upgradeThreadsTableToAutoIncrement(SQLiteDatabase db) {
170015156cd6afcc7ed57ac7be40ef2d32a615e83599Tom Taylor        if (hasAutoIncrement(db, MmsSmsProvider.TABLE_THREADS)) {
17011ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor            Log.d(TAG, "[MmsSmsDb] upgradeThreadsTableToAutoIncrement: already upgraded");
17021ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor            return;
17031ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        }
17041ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        Log.d(TAG, "[MmsSmsDb] upgradeThreadsTableToAutoIncrement: upgrading");
17051ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor
17061ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        // Make the _id of the threads table autoincrement so we never re-use thread ids
17071ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        // Have to create a new temp threads table. Copy all the info from the old table.
17081ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        // Drop the old table and rename the new table to that of the old.
17091ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        db.execSQL("CREATE TABLE threads_temp (" +
17101ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
17111ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.DATE + " INTEGER DEFAULT 0," +
17121ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.MESSAGE_COUNT + " INTEGER DEFAULT 0," +
17131ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.RECIPIENT_IDS + " TEXT," +
17141ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.SNIPPET + " TEXT," +
17151ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.SNIPPET_CHARSET + " INTEGER DEFAULT 0," +
17161ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.READ + " INTEGER DEFAULT 1," +
17171ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.TYPE + " INTEGER DEFAULT 0," +
17181ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.ERROR + " INTEGER DEFAULT 0," +
17191ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor                Threads.HAS_ATTACHMENT + " INTEGER DEFAULT 0);");
17201ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor
17211ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        db.execSQL("INSERT INTO threads_temp SELECT * from threads;");
17221ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        db.execSQL("DROP TABLE threads;");
17231ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor        db.execSQL("ALTER TABLE threads_temp RENAME TO threads;");
17241ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor    }
17251ab4800f1598cae72846ae4d24d6c545a5965d97Tom Taylor
172609710cec4926bcd3708376face04507e661bcc02Tom Taylor    // upgradeAddressTableToAutoIncrement() is called to add the AUTOINCREMENT keyword to
172709710cec4926bcd3708376face04507e661bcc02Tom Taylor    // the canonical_addresses table. This could fail if the user has a lot of people they've
172809710cec4926bcd3708376face04507e661bcc02Tom Taylor    // messaged with and not enough storage to make a copy of the canonical_addresses table.
172909710cec4926bcd3708376face04507e661bcc02Tom Taylor    // That's ok. This upgrade is optional. It'll be called again next time the device is rebooted.
173009710cec4926bcd3708376face04507e661bcc02Tom Taylor    private void upgradeAddressTableToAutoIncrement(SQLiteDatabase db) {
173109710cec4926bcd3708376face04507e661bcc02Tom Taylor        if (hasAutoIncrement(db, "canonical_addresses")) {
173209710cec4926bcd3708376face04507e661bcc02Tom Taylor            Log.d(TAG, "[MmsSmsDb] upgradeAddressTableToAutoIncrement: already upgraded");
173309710cec4926bcd3708376face04507e661bcc02Tom Taylor            return;
173409710cec4926bcd3708376face04507e661bcc02Tom Taylor        }
173509710cec4926bcd3708376face04507e661bcc02Tom Taylor        Log.d(TAG, "[MmsSmsDb] upgradeAddressTableToAutoIncrement: upgrading");
173609710cec4926bcd3708376face04507e661bcc02Tom Taylor
173709710cec4926bcd3708376face04507e661bcc02Tom Taylor        // Make the _id of the canonical_addresses table autoincrement so we never re-use ids
173809710cec4926bcd3708376face04507e661bcc02Tom Taylor        // Have to create a new temp canonical_addresses table. Copy all the info from the old
173909710cec4926bcd3708376face04507e661bcc02Tom Taylor        // table. Drop the old table and rename the new table to that of the old.
174009710cec4926bcd3708376face04507e661bcc02Tom Taylor        db.execSQL("CREATE TABLE canonical_addresses_temp (_id INTEGER PRIMARY KEY AUTOINCREMENT," +
174109710cec4926bcd3708376face04507e661bcc02Tom Taylor                "address TEXT);");
174209710cec4926bcd3708376face04507e661bcc02Tom Taylor
174309710cec4926bcd3708376face04507e661bcc02Tom Taylor        db.execSQL("INSERT INTO canonical_addresses_temp SELECT * from canonical_addresses;");
174409710cec4926bcd3708376face04507e661bcc02Tom Taylor        db.execSQL("DROP TABLE canonical_addresses;");
174509710cec4926bcd3708376face04507e661bcc02Tom Taylor        db.execSQL("ALTER TABLE canonical_addresses_temp RENAME TO canonical_addresses;");
174609710cec4926bcd3708376face04507e661bcc02Tom Taylor    }
174709710cec4926bcd3708376face04507e661bcc02Tom Taylor
174849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor    // upgradePartTableToAutoIncrement() is called to add the AUTOINCREMENT keyword to
174949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor    // the part table. This could fail if the user has a lot of sound/video/picture attachments
175049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor    // and not enough storage to make a copy of the part table.
175149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor    // That's ok. This upgrade is optional. It'll be called again next time the device is rebooted.
175249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor    private void upgradePartTableToAutoIncrement(SQLiteDatabase db) {
175349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        if (hasAutoIncrement(db, "part")) {
175449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor            Log.d(TAG, "[MmsSmsDb] upgradePartTableToAutoIncrement: already upgraded");
175549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor            return;
175649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        }
175749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        Log.d(TAG, "[MmsSmsDb] upgradePartTableToAutoIncrement: upgrading");
175849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
175949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // Make the _id of the part table autoincrement so we never re-use ids
176049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // Have to create a new temp part table. Copy all the info from the old
176149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // table. Drop the old table and rename the new table to that of the old.
176249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("CREATE TABLE part_temp (" +
176349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Part._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
176449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Part.MSG_ID + " INTEGER," +
176549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Part.SEQ + " INTEGER DEFAULT 0," +
176649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Part.CONTENT_TYPE + " TEXT," +
176749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Part.NAME + " TEXT," +
176849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Part.CHARSET + " INTEGER," +
176949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Part.CONTENT_DISPOSITION + " TEXT," +
177049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Part.FILENAME + " TEXT," +
177149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Part.CONTENT_ID + " TEXT," +
177249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Part.CONTENT_LOCATION + " TEXT," +
177349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Part.CT_START + " INTEGER," +
177449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Part.CT_TYPE + " TEXT," +
177549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Part._DATA + " TEXT," +
177649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Part.TEXT + " TEXT);");
177749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
177849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("INSERT INTO part_temp SELECT * from part;");
177949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TABLE part;");
178049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("ALTER TABLE part_temp RENAME TO part;");
178149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
178249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // part-related triggers get tossed when the part table is dropped -- rebuild them.
178349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        createMmsTriggers(db);
178449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor    }
178549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
178649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor    // upgradePduTableToAutoIncrement() is called to add the AUTOINCREMENT keyword to
178749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor    // the pdu table. This could fail if the user has a lot of mms messages
178849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor    // and not enough storage to make a copy of the pdu table.
178949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor    // That's ok. This upgrade is optional. It'll be called again next time the device is rebooted.
179049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor    private void upgradePduTableToAutoIncrement(SQLiteDatabase db) {
179149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        if (hasAutoIncrement(db, "pdu")) {
179249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor            Log.d(TAG, "[MmsSmsDb] upgradePduTableToAutoIncrement: already upgraded");
179349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor            return;
179449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        }
179549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        Log.d(TAG, "[MmsSmsDb] upgradePduTableToAutoIncrement: upgrading");
179649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
179749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // Make the _id of the part table autoincrement so we never re-use ids
179849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // Have to create a new temp part table. Copy all the info from the old
179949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // table. Drop the old table and rename the new table to that of the old.
180049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("CREATE TABLE pdu_temp (" +
180149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
180249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.THREAD_ID + " INTEGER," +
180349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.DATE + " INTEGER," +
180449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.DATE_SENT + " INTEGER DEFAULT 0," +
180549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.MESSAGE_BOX + " INTEGER," +
180649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.READ + " INTEGER DEFAULT 0," +
180749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.MESSAGE_ID + " TEXT," +
180849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.SUBJECT + " TEXT," +
180949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.SUBJECT_CHARSET + " INTEGER," +
181049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.CONTENT_TYPE + " TEXT," +
181149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.CONTENT_LOCATION + " TEXT," +
181249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.EXPIRY + " INTEGER," +
181349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.MESSAGE_CLASS + " TEXT," +
181449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.MESSAGE_TYPE + " INTEGER," +
181549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.MMS_VERSION + " INTEGER," +
181649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.MESSAGE_SIZE + " INTEGER," +
181749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.PRIORITY + " INTEGER," +
181849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.READ_REPORT + " INTEGER," +
181949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.REPORT_ALLOWED + " INTEGER," +
182049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.RESPONSE_STATUS + " INTEGER," +
182149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.STATUS + " INTEGER," +
182249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.TRANSACTION_ID + " TEXT," +
182349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.RETRIEVE_STATUS + " INTEGER," +
182449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.RETRIEVE_TEXT + " TEXT," +
182549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.RETRIEVE_TEXT_CHARSET + " INTEGER," +
182649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.READ_STATUS + " INTEGER," +
182749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.CONTENT_CLASS + " INTEGER," +
182849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.RESPONSE_TEXT + " TEXT," +
182949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.DELIVERY_TIME + " INTEGER," +
183049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.DELIVERY_REPORT + " INTEGER," +
183149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.LOCKED + " INTEGER DEFAULT 0," +
1832cfb8bbdc3932473966d043fbd72b6c067933f2c1Ye Wen                Mms.SUB_ID + " INTEGER DEFAULT -1," +
183349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.SEEN + " INTEGER DEFAULT 0," +
183449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                Mms.TEXT_ONLY + " INTEGER DEFAULT 0" +
183549c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor                ");");
183649c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
183749c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("INSERT INTO pdu_temp SELECT * from pdu;");
183849c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("DROP TABLE pdu;");
183949c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        db.execSQL("ALTER TABLE pdu_temp RENAME TO pdu;");
184049c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
184149c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        // pdu-related triggers get tossed when the part table is dropped -- rebuild them.
184249c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor        createMmsTriggers(db);
184349c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor    }
184449c9ede3206cf2b9504cb9d06deeea8fd856900cTom Taylor
184510faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor    private class LowStorageMonitor extends BroadcastReceiver {
184610faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor
184710faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        public LowStorageMonitor() {
184810faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        }
184910faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor
185010faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        public void onReceive(Context context, Intent intent) {
185110faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor            String action = intent.getAction();
185210faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor
185310faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor            Log.d(TAG, "[LowStorageMonitor] onReceive intent " + action);
185410faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor
185510faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor            if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) {
185610faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor                sTriedAutoIncrement = false;    // try to upgrade on the next getWriteableDatabase
185710faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor            }
185810faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor        }
185910faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor    }
186010faf3f5f0c16a812c25f02d208715fabc556a7dTom Taylor
18611047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang    private void updateThreadsAttachmentColumn(SQLiteDatabase db) {
18621047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        // Set the values of that column correctly based on the current
18631047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        // contents of the database.
18641047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang        db.execSQL("UPDATE threads SET has_attachment=1 WHERE _id IN " +
18651047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                   "  (SELECT DISTINCT pdu.thread_id FROM part " +
18661047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                   "   JOIN pdu ON pdu._id=part.mid " +
18671047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang                   "   WHERE part.ct != 'text/plain' AND part.ct != 'application/smil')");
18681047ab43a2bcdad9b8e8cf27afabe40ab8608b3dWei Huang    }
18697236c3ad7ff01dd5ece14a2cabbf5ce3a570d793The Android Open Source Project}
1870