1b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey/*
2b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Copyright (C) 2009 The Android Open Source Project
3b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
4b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * you may not use this file except in compliance with the License.
6b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * You may obtain a copy of the License at
7b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
8b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
10b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Unless required by applicable law or agreed to in writing, software
11b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * See the License for the specific language governing permissions and
14b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * limitations under the License
15b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey */
16b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarpackage com.android.providers.contacts;
18b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1953214b3ed12b0ff9cb589b6559311f2ac142f2e3Bjorn Bringertimport com.android.common.content.SyncStateContentProviderHelper;
2067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
2182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.content.ContentResolver;
22619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.ContentValues;
23b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.content.Context;
24619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.ApplicationInfo;
25619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.PackageManager;
26619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
27d91272b48f97243533c6580981e12a4847b5783fJeff Hamiltonimport android.content.res.Resources;
288ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikovimport android.database.CharArrayBuffer;
2936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikovimport android.database.Cursor;
30b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.DatabaseUtils;
31f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikovimport android.database.SQLException;
3278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException;
33b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteDatabase;
34b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteDoneException;
35b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikovimport android.database.sqlite.SQLiteException;
36b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteOpenHelper;
37bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikovimport android.database.sqlite.SQLiteQueryBuilder;
38b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteStatement;
39892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikovimport android.location.CountryDetector;
40fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikovimport android.net.Uri;
414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikovimport android.os.Binder;
42a3bd0246ca3741877488bca7aadd91c79b2fd8d2Fred Quintanaimport android.os.Bundle;
43c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamiltonimport android.os.SystemClock;
44b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.provider.BaseColumns;
45e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.provider.CallLog.Calls;
46a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract;
47b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions;
48a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email;
49a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.GroupMembership;
502a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im;
51a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname;
52a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization;
53a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone;
54a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.SipAddress;
55a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName;
567cf50494501938f175d288077145acf49da8f171Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
57d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.Contacts;
583d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikovimport android.provider.ContactsContract.Contacts.Photo;
59de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.Data;
60d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.provider.ContactsContract.Directory;
615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.DisplayNameSources;
62b2197b235e3d96e7f70c24d548b7dac52dab88d8Flavio Lerdaimport android.provider.ContactsContract.DisplayPhoto;
635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.FullNameStyle;
64ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.Groups;
658ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikovimport android.provider.ContactsContract.PhoneticNameStyle;
66f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport android.provider.ContactsContract.PhotoFiles;
67d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts;
68eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkeyimport android.provider.ContactsContract.Settings;
6982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates;
703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmannimport android.provider.ContactsContract.StreamItemPhotos;
71ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmannimport android.provider.ContactsContract.StreamItems;
7267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.SocialContract.Activities;
73069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjeeimport android.provider.VoicemailContract;
7459f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjeeimport android.provider.VoicemailContract.Voicemails;
75bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikovimport android.telephony.PhoneNumberUtils;
7636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikovimport android.text.TextUtils;
77b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikovimport android.text.util.Rfc822Token;
78b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikovimport android.text.util.Rfc822Tokenizer;
79b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.util.Log;
80b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
81b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport java.util.HashMap;
825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport java.util.Locale;
83b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
84b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey/**
85b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov * Database helper for contacts. Designed as a singleton to make sure that all
86b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov * {@link android.content.ContentProvider} users get the same reference.
87b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov * Provides handy methods for maintaining package and mime-type lookup tables.
88b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey */
89b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov/* package */ class ContactsDatabaseHelper extends SQLiteOpenHelper {
90b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    private static final String TAG = "ContactsDatabaseHelper";
91b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
9297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    /**
9394c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov     * Contacts DB version ranges:
9497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     * <pre>
9597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   0-98    Cupcake/Donut
9697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   100-199 Eclair
9797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   200-299 Eclair-MR1
9897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   300-349 Froyo
9997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   350-399 Gingerbread
10097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   400-499 Honeycomb
10124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro     *   500-549 Honeycomb-MR1
10224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro     *   550-599 Honeycomb-MR2
10324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro     *   600-699 Ice Cream Sandwich
10497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     * </pre>
10597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     */
106f5f038faf7f3ef460e1c11028d467954840e5f6fMakoto Onuki    static final int DATABASE_VERSION = 625;
107e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
108b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private static final String DATABASE_NAME = "contacts2.db";
1091f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    private static final String DATABASE_PRESENCE = "presence_db";
110b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
111b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface Tables {
112d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONTACTS = "contacts";
1135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACTS = "raw_contacts";
1143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann        public static final String STREAM_ITEMS = "stream_items";
1153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann        public static final String STREAM_ITEM_PHOTOS = "stream_item_photos";
116f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro        public static final String PHOTO_FILES = "photo_files";
117ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String PACKAGES = "packages";
118ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String MIMETYPES = "mimetypes";
119b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PHONE_LOOKUP = "phone_lookup";
120a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NAME_LOOKUP = "name_lookup";
121b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        public static final String AGGREGATION_EXCEPTIONS = "agg_exceptions";
122eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        public static final String SETTINGS = "settings";
123b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA = "data";
124ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String GROUPS = "groups";
1251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        public static final String PRESENCE = "presence";
126e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        public static final String AGGREGATED_PRESENCE = "agg_presence";
127b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String NICKNAME_LOOKUP = "nickname_lookup";
128e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        public static final String CALLS = "calls";
129a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        public static final String STATUS_UPDATES = "status_updates";
130b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        public static final String PROPERTIES = "properties";
131743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        public static final String ACCOUNTS = "accounts";
1324394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        public static final String VISIBLE_CONTACTS = "visible_contacts";
133d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        public static final String DIRECTORIES = "directories";
134385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        public static final String DEFAULT_DIRECTORY = "default_directory";
135f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov        public static final String SEARCH_INDEX = "search_index";
136069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee        public static final String VOICEMAIL_STATUS = "voicemail_status";
137b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        // This list of tables contains auto-incremented sequences.
1395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        public static final String[] SEQUENCE_TABLES = new String[] {
1405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                CONTACTS,
1415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                RAW_CONTACTS,
1425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                STREAM_ITEMS,
1435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                STREAM_ITEM_PHOTOS,
1445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                PHOTO_FILES,
1455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                DATA,
1465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                GROUPS,
1475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                CALLS,
1485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                DIRECTORIES
1495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        };
1505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro
15146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        /**
15246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa         * For {@link ContactsContract.DataUsageFeedback}. The table structure itself
15346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa         * is not exposed outside.
15446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa         */
15546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        public static final String DATA_USAGE_STAT = "data_usage_stat";
15646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa
157ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String DATA_JOIN_MIMETYPES = "data "
1581b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id)";
159b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
16011944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        public static final String DATA_JOIN_RAW_CONTACTS = "data "
1618e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id)";
16211944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
1635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String DATA_JOIN_MIMETYPE_RAW_CONTACTS = "data "
164c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
165c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id)";
166bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
167e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        // NOTE: This requires late binding of GroupMembership MIME-type
168e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String RAW_CONTACTS_JOIN_SETTINGS_DATA_GROUPS = "raw_contacts "
169e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN settings ON ("
170e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_name = settings.account_name AND "
171f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                    + "raw_contacts.account_type = settings.account_type AND "
172f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                    + "((raw_contacts.data_set IS NULL AND settings.data_set IS NULL) "
173f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                    + "OR (raw_contacts.data_set = settings.data_set))) "
174e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN data ON (data.mimetype_id=? AND "
175e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "data.raw_contact_id = raw_contacts._id) "
176e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN groups ON (groups._id = data." + GroupMembership.GROUP_ROW_ID
177e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + ")";
178e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
179e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        // NOTE: This requires late binding of GroupMembership MIME-type
180e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS = "settings "
181e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN raw_contacts ON ("
182e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_name = settings.account_name AND "
183e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_type = settings.account_type) "
184e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN data ON (data.mimetype_id=? AND "
185e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "data.raw_contact_id = raw_contacts._id) "
186e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
187e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
188f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa        public static final String CONTACTS_JOIN_RAW_CONTACTS_DATA_FILTERED_BY_GROUPMEMBERSHIP =
189f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                Tables.CONTACTS
190f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                    + " INNER JOIN " + Tables.RAW_CONTACTS
191f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                        + " ON (" + RawContactsColumns.CONCRETE_CONTACT_ID + "="
192f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                            + ContactsColumns.CONCRETE_ID
193f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                        + ")"
194f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                    + " INNER JOIN " + Tables.DATA
195f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                        + " ON (" + DataColumns.CONCRETE_DATA1 + "=" + GroupsColumns.CONCRETE_ID
196f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                        + " AND "
197f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                        + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID
198f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                        + " AND "
199f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                        + DataColumns.CONCRETE_MIMETYPE_ID + "="
200f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                            + "(SELECT " + MimetypesColumns._ID
201f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                            + " FROM " + Tables.MIMETYPES
202f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                            + " WHERE "
203f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                            + MimetypesColumns.CONCRETE_MIMETYPE + "="
204f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                                + "'" + GroupMembership.CONTENT_ITEM_TYPE + "'"
205f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                            + ")"
206f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa                        + ")";
207ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
2085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_GROUPS = "data "
2091b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
2101b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) "
21167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                + "LEFT OUTER JOIN packages ON (data.package_id = packages._id) "
2129261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "LEFT OUTER JOIN groups "
2139261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "  ON (mimetypes.mimetype='" + GroupMembership.CONTENT_ITEM_TYPE + "' "
2149261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "      AND groups._id = data." + GroupMembership.GROUP_ROW_ID + ") ";
215ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
216ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String GROUPS_JOIN_PACKAGES = "groups "
217ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN packages ON (groups.package_id = packages._id)";
218ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
219b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
220b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String ACTIVITIES = "activities";
221b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
222ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String ACTIVITIES_JOIN_MIMETYPES = "activities "
223ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (activities.mimetype_id = mimetypes._id)";
224b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
225d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String ACTIVITIES_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS =
2265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                "activities "
22767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                + "LEFT OUTER JOIN packages ON (activities.package_id = packages._id) "
228ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (activities.mimetype_id = mimetypes._id) "
2295ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "LEFT OUTER JOIN raw_contacts ON (activities.author_contact_id = " +
230fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        "raw_contacts._id) "
231d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
2327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana
2335ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String NAME_LOOKUP_JOIN_RAW_CONTACTS = "name_lookup "
23403975f7ca8bb2f95ce95b6c694612c2524e91d13Dave Santoro                + "INNER JOIN view_raw_contacts ON (name_lookup.raw_contact_id = "
23503975f7ca8bb2f95ce95b6c694612c2524e91d13Dave Santoro                + "view_raw_contacts._id)";
236b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
237b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
23823ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki    public interface Joins {
23923ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki        /**
24023ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki         * Join string intended to be used with the GROUPS table/view.  The main table must be named
24123ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki         * as "groups".
24223ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki         *
24323ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki         * Adds the "group_member_count column" to the query, which will be null if a group has
24423ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki         * no members.  Use ifnull(group_member_count, 0) if 0 is needed instead.
24523ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki         */
24623ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki        public static final String GROUP_MEMBER_COUNT =
24723ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki                " LEFT OUTER JOIN (SELECT "
24823ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki                        + "data.data1 AS member_count_group_id, "
24923ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki                        + "COUNT(data.raw_contact_id) AS group_member_count "
25023ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki                    + "FROM data "
25123ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki                    + "WHERE "
25223ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki                        + "data.mimetype_id = (SELECT _id FROM mimetypes WHERE "
25323ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki                            + "mimetypes.mimetype = '" + GroupMembership.CONTENT_ITEM_TYPE + "')"
25423ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki                    + "GROUP BY member_count_group_id) AS member_count_table" // End of inner query
25523ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki                + " ON (groups._id = member_count_table.member_count_group_id)";
25623ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki    }
25723ba865a6d204ba4aa29d2fad9989e9c44351e81Makoto Onuki
2584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public interface Views {
259ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        public static final String DATA = "view_data";
260ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        public static final String RAW_CONTACTS = "view_raw_contacts";
261ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        public static final String CONTACTS = "view_contacts";
262a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        public static final String ENTITIES = "view_entities";
263a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        public static final String RAW_ENTITIES = "view_raw_entities";
264ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        public static final String GROUPS = "view_groups";
265ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        public static final String DATA_USAGE_STAT = "view_data_usage_stat";
2669b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann        public static final String STREAM_ITEMS = "view_stream_items";
2674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
2684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
2691f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    public interface Clauses {
27068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey        final String HAVING_NO_GROUPS = "COUNT(" + DataColumns.CONCRETE_GROUP_ID + ") == 0";
2719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana
27268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey        final String GROUP_BY_ACCOUNT_CONTACT_ID = SettingsColumns.CONCRETE_ACCOUNT_NAME + ","
27368936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey                + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "," + RawContacts.CONTACT_ID;
274e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
275e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String RAW_CONTACT_IS_LOCAL = RawContactsColumns.CONCRETE_ACCOUNT_NAME
27643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                + " IS NULL AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL AND "
27743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                + RawContactsColumns.CONCRETE_DATA_SET + " IS NULL";
278e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
279e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String ZERO_GROUP_MEMBERSHIPS = "COUNT(" + GroupsColumns.CONCRETE_ID + ")=0";
280e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
2811a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey        final String OUTER_RAW_CONTACTS = "outer_raw_contacts";
2821a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey        final String OUTER_RAW_CONTACTS_ID = OUTER_RAW_CONTACTS + "." + RawContacts._ID;
2831a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey
284b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov        final String CONTACT_IS_VISIBLE =
285b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                "SELECT " +
2861a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey                    "MAX((SELECT (CASE WHEN " +
287b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                        "(CASE" +
288b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " WHEN " + RAW_CONTACT_IS_LOCAL +
289b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " THEN 1 " +
290b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " WHEN " + ZERO_GROUP_MEMBERSHIPS +
291b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " THEN " + Settings.UNGROUPED_VISIBLE +
292b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " ELSE MAX(" + Groups.GROUP_VISIBLE + ")" +
293b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                         "END)=1 THEN 1 ELSE 0 END)" +
294b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS_JOIN_SETTINGS_DATA_GROUPS +
2951a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey                " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + OUTER_RAW_CONTACTS_ID + "))" +
2961a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey                " FROM " + Tables.RAW_CONTACTS + " AS " + OUTER_RAW_CONTACTS +
297b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
298b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                " GROUP BY " + RawContacts.CONTACT_ID;
299e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
300e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String GROUP_HAS_ACCOUNT_AND_SOURCE_ID = Groups.SOURCE_ID + "=? AND "
30143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                + Groups.ACCOUNT_NAME + "=? AND " + Groups.ACCOUNT_TYPE + "=? AND "
30243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                + Groups.DATA_SET + " IS NULL";
30343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro
30443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        final String GROUP_HAS_ACCOUNT_AND_DATA_SET_AND_SOURCE_ID = Groups.SOURCE_ID + "=? AND "
30543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                + Groups.ACCOUNT_NAME + "=? AND " + Groups.ACCOUNT_TYPE + "=? AND "
30643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                + Groups.DATA_SET + "=?";
3074394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
3084394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        public static final String CONTACT_VISIBLE =
3094394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            "EXISTS (SELECT _id FROM " + Tables.VISIBLE_CONTACTS
3104394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                + " WHERE " + Tables.CONTACTS +"." + Contacts._ID
3114394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        + "=" + Tables.VISIBLE_CONTACTS +"." + Contacts._ID + ")";
3121f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    }
3131f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
314d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    public interface ContactsColumns {
315a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        public static final String LAST_STATUS_UPDATE_ID = "status_update_id";
316a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov
317d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_ID = Tables.CONTACTS + "." + BaseColumns._ID;
31867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
319f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro        public static final String CONCRETE_PHOTO_FILE_ID = Tables.CONTACTS + "."
320f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + Contacts.PHOTO_FILE_ID;
321d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_TIMES_CONTACTED = Tables.CONTACTS + "."
322d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.TIMES_CONTACTED;
323d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_LAST_TIME_CONTACTED = Tables.CONTACTS + "."
324d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.LAST_TIME_CONTACTED;
325d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_STARRED = Tables.CONTACTS + "." + Contacts.STARRED;
326d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_CUSTOM_RINGTONE = Tables.CONTACTS + "."
327d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.CUSTOM_RINGTONE;
328d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_SEND_TO_VOICEMAIL = Tables.CONTACTS + "."
329d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.SEND_TO_VOICEMAIL;
3302d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill        public static final String CONCRETE_LOOKUP_KEY = Tables.CONTACTS + "."
3312d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill                + Contacts.LOOKUP_KEY;
332619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
333619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
3346cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov    public interface RawContactsColumns {
33533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_ID =
3365ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + BaseColumns._ID;
3379261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana        public static final String CONCRETE_ACCOUNT_NAME =
3385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.ACCOUNT_NAME;
3399261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana        public static final String CONCRETE_ACCOUNT_TYPE =
3405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.ACCOUNT_TYPE;
34143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        public static final String CONCRETE_DATA_SET =
34243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                Tables.RAW_CONTACTS + "." + RawContacts.DATA_SET;
34343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        public static final String CONCRETE_ACCOUNT_TYPE_AND_DATA_SET =
34443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                Tables.RAW_CONTACTS + "." + RawContacts.ACCOUNT_TYPE_AND_DATA_SET;
34533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_SOURCE_ID =
3465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.SOURCE_ID;
34733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_VERSION =
3485ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.VERSION;
34933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_DIRTY =
3505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.DIRTY;
35133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_DELETED =
3525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.DELETED;
3537a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC1 =
3547a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC1;
3557a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC2 =
3567a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC2;
3577a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC3 =
3587a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC3;
3597a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC4 =
3607a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC4;
36124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro        public static final String CONCRETE_CUSTOM_RINGTONE =
36224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro                Tables.RAW_CONTACTS + "." + RawContacts.CUSTOM_RINGTONE;
36324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro        public static final String CONCRETE_SEND_TO_VOICEMAIL =
36424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro                Tables.RAW_CONTACTS + "." + RawContacts.SEND_TO_VOICEMAIL;
36524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro        public static final String CONCRETE_LAST_TIME_CONTACTED =
36624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro                Tables.RAW_CONTACTS + "." + RawContacts.LAST_TIME_CONTACTED;
36724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro        public static final String CONCRETE_TIMES_CONTACTED =
36824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro                Tables.RAW_CONTACTS + "." + RawContacts.TIMES_CONTACTED;
369c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey        public static final String CONCRETE_STARRED =
370c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey                Tables.RAW_CONTACTS + "." + RawContacts.STARRED;
3718e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov
3725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        public static final String DISPLAY_NAME = RawContacts.DISPLAY_NAME_PRIMARY;
3735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        public static final String DISPLAY_NAME_SOURCE = RawContacts.DISPLAY_NAME_SOURCE;
3748e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov        public static final String AGGREGATION_NEEDED = "aggregation_needed";
375fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
376fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        public static final String CONCRETE_DISPLAY_NAME =
377fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Tables.RAW_CONTACTS + "." + DISPLAY_NAME;
378fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        public static final String CONCRETE_CONTACT_ID =
379fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.CONTACT_ID;
380f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        public static final String CONCRETE_NAME_VERIFIED =
381f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.NAME_VERIFIED;
382619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
383619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
384619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    public interface DataColumns {
38567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String PACKAGE_ID = "package_id";
386b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE_ID = "mimetype_id";
387ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
388ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.DATA + "." + BaseColumns._ID;
389226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_MIMETYPE_ID = Tables.DATA + "." + MIMETYPE_ID;
390d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_RAW_CONTACT_ID = Tables.DATA + "."
391d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Data.RAW_CONTACT_ID;
392ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_GROUP_ID = Tables.DATA + "."
393ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + GroupMembership.GROUP_ROW_ID;
394e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov
395e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA1 = Tables.DATA + "." + Data.DATA1;
396e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA2 = Tables.DATA + "." + Data.DATA2;
397e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA3 = Tables.DATA + "." + Data.DATA3;
398e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA4 = Tables.DATA + "." + Data.DATA4;
399e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA5 = Tables.DATA + "." + Data.DATA5;
400e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA6 = Tables.DATA + "." + Data.DATA6;
401e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA7 = Tables.DATA + "." + Data.DATA7;
402e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA8 = Tables.DATA + "." + Data.DATA8;
403e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA9 = Tables.DATA + "." + Data.DATA9;
404e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA10 = Tables.DATA + "." + Data.DATA10;
4050f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA11 = Tables.DATA + "." + Data.DATA11;
4060f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA12 = Tables.DATA + "." + Data.DATA12;
4070f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA13 = Tables.DATA + "." + Data.DATA13;
4080f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA14 = Tables.DATA + "." + Data.DATA14;
4090f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA15 = Tables.DATA + "." + Data.DATA15;
410e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_IS_PRIMARY = Tables.DATA + "." + Data.IS_PRIMARY;
411226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_PACKAGE_ID = Tables.DATA + "." + PACKAGE_ID;
412e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov    }
413e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov
4140f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    // Used only for legacy API support
4150f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    public interface ExtensionsColumns {
4160f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String NAME = Data.DATA1;
4170f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String VALUE = Data.DATA2;
4180f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    }
4190f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov
4200f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    public interface GroupMembershipColumns {
4215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = Data.RAW_CONTACT_ID;
4220f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String GROUP_ROW_ID = GroupMembership.GROUP_ROW_ID;
4230f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    }
4240f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov
425e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov    public interface PhoneColumns {
426e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String NORMALIZED_NUMBER = Data.DATA4;
427e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_NORMALIZED_NUMBER = DataColumns.CONCRETE_DATA4;
428ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
429ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
430ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface GroupsColumns {
43167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String PACKAGE_ID = "package_id";
43267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
433ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.GROUPS + "." + BaseColumns._ID;
43467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String CONCRETE_SOURCE_ID = Tables.GROUPS + "." + Groups.SOURCE_ID;
4351cdfc9dacc136e99d3c0bc5b4212bc3c973be337Daniel Lehmann        public static final String CONCRETE_ACCOUNT_NAME =
4361cdfc9dacc136e99d3c0bc5b4212bc3c973be337Daniel Lehmann                Tables.GROUPS + "." + Groups.ACCOUNT_NAME;
4371cdfc9dacc136e99d3c0bc5b4212bc3c973be337Daniel Lehmann        public static final String CONCRETE_ACCOUNT_TYPE =
4381cdfc9dacc136e99d3c0bc5b4212bc3c973be337Daniel Lehmann                Tables.GROUPS + "." + Groups.ACCOUNT_TYPE;
43943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        public static final String CONCRETE_DATA_SET = Tables.GROUPS + "." + Groups.DATA_SET;
44043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        public static final String CONCRETE_ACCOUNT_TYPE_AND_DATA_SET = Tables.GROUPS + "." +
44143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                Groups.ACCOUNT_TYPE_AND_DATA_SET;
442341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey    }
443b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
444b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface ActivitiesColumns {
445b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PACKAGE_ID = "package_id";
446b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE_ID = "mimetype_id";
447b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
448b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
449b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface PhoneLookupColumns {
450b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
451b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA_ID = "data_id";
4525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = "raw_contact_id";
453b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String NORMALIZED_NUMBER = "normalized_number";
45436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        public static final String MIN_MATCH = "min_match";
455b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
456b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
457a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    public interface NameLookupColumns {
4585ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = "raw_contact_id";
45914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        public static final String DATA_ID = "data_id";
460a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NORMALIZED_NAME = "normalized_name";
461a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NAME_TYPE = "name_type";
462a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
463a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
464a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov    public final static class NameLookupType {
4652a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NAME_EXACT = 0;
4662a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NAME_VARIANT = 1;
4672a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NAME_COLLATION_KEY = 2;
4682a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NICKNAME = 3;
4692a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int EMAIL_BASED_NICKNAME = 4;
470a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
471a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        // This is the highest name lookup type code plus one
47292ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov        public static final int TYPE_COUNT = 5;
473a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov
474a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        public static boolean isBasedOnStructuredName(int nameLookupType) {
4752a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov            return nameLookupType == NameLookupType.NAME_EXACT
4762a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov                    || nameLookupType == NameLookupType.NAME_VARIANT
4772a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov                    || nameLookupType == NameLookupType.NAME_COLLATION_KEY;
478a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        }
479a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
480a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
481ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface PackagesColumns {
482b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
483b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PACKAGE = "package";
484226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana
485226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_ID = Tables.PACKAGES + "." + _ID;
486b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
487b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
488ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface MimetypesColumns {
489b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
490b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE = "mimetype";
491ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
492ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.MIMETYPES + "." + BaseColumns._ID;
493ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_MIMETYPE = Tables.MIMETYPES + "." + MIMETYPE;
494b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
495b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
496b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov    public interface AggregationExceptionColumns {
497b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        public static final String _ID = BaseColumns._ID;
498b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov    }
499b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
500b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    public interface NicknameLookupColumns {
501b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String NAME = "name";
502b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String CLUSTER = "cluster";
503b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    }
504b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
505e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey    public interface SettingsColumns {
506e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String CONCRETE_ACCOUNT_NAME = Tables.SETTINGS + "."
507e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + Settings.ACCOUNT_NAME;
508e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String CONCRETE_ACCOUNT_TYPE = Tables.SETTINGS + "."
509e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + Settings.ACCOUNT_TYPE;
510f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro        public static final String CONCRETE_DATA_SET = Tables.SETTINGS + "."
511f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                + Settings.DATA_SET;
512e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey    }
513e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
5144dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov    public interface PresenceColumns {
5154dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov        String RAW_CONTACT_ID = "presence_raw_contact_id";
516bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        String CONTACT_ID = "presence_contact_id";
5174dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov    }
5184dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov
519e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov    public interface AggregatedPresenceColumns {
520e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        String CONTACT_ID = "presence_contact_id";
5213296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
5223296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_CONTACT_ID = Tables.AGGREGATED_PRESENCE + "." + CONTACT_ID;
523e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov    }
524e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov
525a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov    public interface StatusUpdatesColumns {
526a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        String DATA_ID = "status_update_data_id";
5273296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
5283296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_DATA_ID = Tables.STATUS_UPDATES + "." + DATA_ID;
5293296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
5303296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_PRESENCE = Tables.STATUS_UPDATES + "." + StatusUpdates.PRESENCE;
5313296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS = Tables.STATUS_UPDATES + "." + StatusUpdates.STATUS;
5323296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_TIMESTAMP = Tables.STATUS_UPDATES + "."
5333296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey                + StatusUpdates.STATUS_TIMESTAMP;
5343296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_RES_PACKAGE = Tables.STATUS_UPDATES + "."
5353296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey                + StatusUpdates.STATUS_RES_PACKAGE;
5363296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_LABEL = Tables.STATUS_UPDATES + "." + StatusUpdates.STATUS_LABEL;
5373296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_ICON = Tables.STATUS_UPDATES + "." + StatusUpdates.STATUS_ICON;
5383296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey    }
5393296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
5403296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey    public interface ContactsStatusUpdatesColumns {
5413296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String ALIAS = "contacts_" + Tables.STATUS_UPDATES;
5423296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
5433296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_DATA_ID = ALIAS + "." + StatusUpdatesColumns.DATA_ID;
5443296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
5453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_PRESENCE = ALIAS + "." + StatusUpdates.PRESENCE;
5463296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS = ALIAS + "." + StatusUpdates.STATUS;
5473296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_TIMESTAMP = ALIAS + "." + StatusUpdates.STATUS_TIMESTAMP;
5483296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_RES_PACKAGE = ALIAS + "." + StatusUpdates.STATUS_RES_PACKAGE;
5493296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_LABEL = ALIAS + "." + StatusUpdates.STATUS_LABEL;
5503296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_ICON = ALIAS + "." + StatusUpdates.STATUS_ICON;
551a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov    }
552a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov
5533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann    public interface StreamItemsColumns {
5540bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_ID = Tables.STREAM_ITEMS + "." + BaseColumns._ID;
5550bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_RAW_CONTACT_ID =
5560bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                Tables.STREAM_ITEMS + "." + StreamItems.RAW_CONTACT_ID;
5570bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_PACKAGE = Tables.STREAM_ITEMS + "." + StreamItems.RES_PACKAGE;
5580bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_ICON = Tables.STREAM_ITEMS + "." + StreamItems.RES_ICON;
5590bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_LABEL = Tables.STREAM_ITEMS + "." + StreamItems.RES_LABEL;
5600bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_TEXT = Tables.STREAM_ITEMS + "." + StreamItems.TEXT;
5610bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_TIMESTAMP = Tables.STREAM_ITEMS + "." + StreamItems.TIMESTAMP;
5620bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_COMMENTS = Tables.STREAM_ITEMS + "." + StreamItems.COMMENTS;
5630bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_SYNC1 = Tables.STREAM_ITEMS + "." + StreamItems.SYNC1;
5640bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_SYNC2 = Tables.STREAM_ITEMS + "." + StreamItems.SYNC2;
5650bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_SYNC3 = Tables.STREAM_ITEMS + "." + StreamItems.SYNC3;
5660bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_SYNC4 = Tables.STREAM_ITEMS + "." + StreamItems.SYNC4;
5673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann    }
5683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann
5693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann    public interface StreamItemPhotosColumns {
5700bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_ID = Tables.STREAM_ITEM_PHOTOS + "." + BaseColumns._ID;
5710bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_STREAM_ITEM_ID = Tables.STREAM_ITEM_PHOTOS + "."
5723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann                + StreamItemPhotos.STREAM_ITEM_ID;
5730bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_SORT_INDEX =
5740bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                Tables.STREAM_ITEM_PHOTOS + "." + StreamItemPhotos.SORT_INDEX;
5750bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_PHOTO_FILE_ID = Tables.STREAM_ITEM_PHOTOS + "."
5766802030a777c0c3ba1dc029c534cca4784260632Dave Santoro                + StreamItemPhotos.PHOTO_FILE_ID;
5770bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_SYNC1 = Tables.STREAM_ITEM_PHOTOS + "." + StreamItemPhotos.SYNC1;
5780bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_SYNC2 = Tables.STREAM_ITEM_PHOTOS + "." + StreamItemPhotos.SYNC2;
5790bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_SYNC3 = Tables.STREAM_ITEM_PHOTOS + "." + StreamItemPhotos.SYNC3;
5800bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        final String CONCRETE_SYNC4 = Tables.STREAM_ITEM_PHOTOS + "." + StreamItemPhotos.SYNC4;
5813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann    }
5823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann
583f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro    public interface PhotoFilesColumns {
584f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro        String CONCRETE_ID = Tables.PHOTO_FILES + "." + BaseColumns._ID;
585f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro        String CONCRETE_HEIGHT = Tables.PHOTO_FILES + "." + PhotoFiles.HEIGHT;
586f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro        String CONCRETE_WIDTH = Tables.PHOTO_FILES + "." + PhotoFiles.WIDTH;
587f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro        String CONCRETE_FILESIZE = Tables.PHOTO_FILES + "." + PhotoFiles.FILESIZE;
588f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro    }
589f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro
590b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public interface PropertiesColumns {
591b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        String PROPERTY_KEY = "property_key";
592b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        String PROPERTY_VALUE = "property_value";
593b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
594b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
59524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro    public interface AccountsColumns {
59624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro        String ACCOUNT_NAME = RawContacts.ACCOUNT_NAME;
59724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro        String ACCOUNT_TYPE = RawContacts.ACCOUNT_TYPE;
59843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        String DATA_SET = RawContacts.DATA_SET;
59924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro    }
60024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro
601e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    public static final class DirectoryColumns {
602e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov        public static final String TYPE_RESOURCE_NAME = "typeResourceName";
603e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    }
604e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov
605f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov    public static final class SearchIndexColumns {
606f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov        public static final String CONTACT_ID = "contact_id";
607f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov        public static final String CONTENT = "content";
608155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov        public static final String NAME = "name";
609f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov        public static final String TOKENS = "tokens";
610f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov    }
611f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov
61246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa    /**
61346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa     * Private table for calculating per-contact-method ranking.
61446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa     */
61546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa    public static final class DataUsageStatColumns {
61646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        /** type: INTEGER (long) */
61746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        public static final String _ID = "stat_id";
61846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        public static final String CONCRETE_ID = Tables.DATA_USAGE_STAT + "." + _ID;
61946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa
62046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        /** type: INTEGER (long) */
62146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        public static final String DATA_ID = "data_id";
62246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        public static final String CONCRETE_DATA_ID = Tables.DATA_USAGE_STAT + "." + DATA_ID;
62346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa
62446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        /** type: INTEGER (long) */
62546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        public static final String LAST_TIME_USED = "last_time_used";
62646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        public static final String CONCRETE_LAST_TIME_USED =
62746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                Tables.DATA_USAGE_STAT + "." + LAST_TIME_USED;
62846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa
62946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        /** type: INTEGER */
63046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        public static final String TIMES_USED = "times_used";
63146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        public static final String CONCRETE_TIMES_USED =
63246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                Tables.DATA_USAGE_STAT + "." + TIMES_USED;
63346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa
63446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        /** type: INTEGER */
63546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        public static final String USAGE_TYPE_INT = "usage_type";
63646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        public static final String CONCRETE_USAGE_TYPE =
63746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                Tables.DATA_USAGE_STAT + "." + USAGE_TYPE_INT;
63846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa
63946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        /**
64046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa         * Integer values for USAGE_TYPE.
64146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa         *
64246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa         * @see ContactsContract.DataUsageFeedback#USAGE_TYPE
64346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa         */
64446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        public static final int USAGE_TYPE_INT_CALL = 0;
64546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        public static final int USAGE_TYPE_INT_LONG_TEXT = 1;
64646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        public static final int USAGE_TYPE_INT_SHORT_TEXT = 2;
64746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa    }
64846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa
6493296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey    /** In-memory cache of previously found MIME-type mappings */
650bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    private final HashMap<String, Long> mMimetypeCache = new HashMap<String, Long>();
651b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** In-memory cache of previously found package name mappings */
652bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    private final HashMap<String, Long> mPackageCache = new HashMap<String, Long>();
653b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
6542a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdEmail;
6552a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdIm;
6562a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdNickname;
6577cf50494501938f175d288077145acf49da8f171Daniel Lehmann    private long mMimeTypeIdOrganization;
6582a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdPhone;
6597cf50494501938f175d288077145acf49da8f171Daniel Lehmann    private long mMimeTypeIdSip;
6607cf50494501938f175d288077145acf49da8f171Daniel Lehmann    private long mMimeTypeIdStructuredName;
6617cf50494501938f175d288077145acf49da8f171Daniel Lehmann    private long mMimeTypeIdStructuredPostal;
662b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
663b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** Compiled statements for querying and inserting mappings */
664d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    private SQLiteStatement mContactIdQuery;
665f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    private SQLiteStatement mAggregationModeQuery;
666b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mDataMimetypeQuery;
667b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mActivitiesMimetypeQuery;
668b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
66978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for setting a data record to the primary. */
67078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mSetPrimaryStatement;
67178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for setting a data record to the super primary. */
67278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mSetSuperPrimaryStatement;
67378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for clearing super primary of a single record. */
67478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mClearSuperPrimaryStatement;
67578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for updating a contact display name */
67678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mRawContactDisplayNameUpdate;
67778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
67878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mNameLookupInsert;
67978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mNameLookupDelete;
68078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateAutoTimestamp;
68178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateInsert;
68278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateReplace;
68378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusAttributionUpdate;
68478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateDelete;
68578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mResetNameVerifiedForOtherRawContacts;
686f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    private SQLiteStatement mContactInDefaultDirectoryQuery;
68778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
688b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private final Context mContext;
6892a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private final boolean mDatabaseOptimizationEnabled;
69035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    private final SyncStateContentProviderHelper mSyncState;
691e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    private final CountryMonitor mCountryMonitor;
6925df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov    private StringBuilder mSb = new StringBuilder();
693f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov
694f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    private boolean mReopenDatabase = false;
695f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
696b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    private static ContactsDatabaseHelper sSingleton = null;
697b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
69836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    private boolean mUseStrictPhoneNumberComparison;
6993a6a49cfb06272e3e25f3c390a9cf4002da6e34dDaisuke Miyakawa
7008ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov    private String[] mSelectionArgs1 = new String[1];
7018ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov    private NameSplitter.Name mName = new NameSplitter.Name();
7028ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov    private CharArrayBuffer mCharArrayBuffer = new CharArrayBuffer(128);
7038ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov    private NameSplitter mNameSplitter;
704f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
705b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    public static synchronized ContactsDatabaseHelper getInstance(Context context) {
706b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (sSingleton == null) {
7072a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            sSingleton = new ContactsDatabaseHelper(context, DATABASE_NAME, true);
708b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
709b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return sSingleton;
710b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
711b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
7121f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    /**
71331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov     * Private constructor, callers except unit tests should obtain an instance through
71435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana     * {@link #getInstance(android.content.Context)} instead.
7151f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey     */
716b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    ContactsDatabaseHelper(Context context) {
7172a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        this(context, null, false);
7182a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
7192a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
7205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro    protected ContactsDatabaseHelper(
7212a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            Context context, String databaseName, boolean optimizationEnabled) {
7222a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        super(context, databaseName, null, DATABASE_VERSION);
7232a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mDatabaseOptimizationEnabled = optimizationEnabled;
724d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        Resources resources = context.getResources();
725619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
726b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        mContext = context;
72728b3769e3fcecae56c3fc70cbcb0f95282b9640eFred Quintana        mSyncState = new SyncStateContentProviderHelper();
728e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        mCountryMonitor = new CountryMonitor(context);
72936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        mUseStrictPhoneNumberComparison =
730d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                resources.getBoolean(
731d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                        com.android.internal.R.bool.config_use_strict_phone_number_comparation);
732b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
733b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
7342a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private void refreshDatabaseCaches(SQLiteDatabase db) {
73578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateDelete = null;
73678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace = null;
73778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateInsert = null;
73878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateAutoTimestamp = null;
73978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusAttributionUpdate = null;
74078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts = null;
74178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate = null;
74278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement = null;
74378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement = null;
74478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement = null;
74578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert = null;
74678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupDelete = null;
74778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mDataMimetypeQuery = null;
74878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mActivitiesMimetypeQuery = null;
74978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mContactIdQuery = null;
75078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mAggregationModeQuery = null;
751f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        mContactInDefaultDirectoryQuery = null;
7522a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
75355e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        populateMimeTypeCache(db);
75455e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov    }
75555e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov
75655e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov    private void populateMimeTypeCache(SQLiteDatabase db) {
7572a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimetypeCache.clear();
7582a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mPackageCache.clear();
7592a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
76011a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        // TODO: This could be optimized into one query instead of 7
76111a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        //        Also: We shouldn't have those fields in the first place. This should just be
76211a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        //        in the cache
76311a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        mMimeTypeIdEmail = lookupMimeTypeId(Email.CONTENT_ITEM_TYPE, db);
76411a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        mMimeTypeIdIm = lookupMimeTypeId(Im.CONTENT_ITEM_TYPE, db);
76511a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        mMimeTypeIdNickname = lookupMimeTypeId(Nickname.CONTENT_ITEM_TYPE, db);
7667cf50494501938f175d288077145acf49da8f171Daniel Lehmann        mMimeTypeIdOrganization = lookupMimeTypeId(Organization.CONTENT_ITEM_TYPE, db);
76711a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        mMimeTypeIdPhone = lookupMimeTypeId(Phone.CONTENT_ITEM_TYPE, db);
7687cf50494501938f175d288077145acf49da8f171Daniel Lehmann        mMimeTypeIdSip = lookupMimeTypeId(SipAddress.CONTENT_ITEM_TYPE, db);
7697cf50494501938f175d288077145acf49da8f171Daniel Lehmann        mMimeTypeIdStructuredName = lookupMimeTypeId(StructuredName.CONTENT_ITEM_TYPE, db);
7707cf50494501938f175d288077145acf49da8f171Daniel Lehmann        mMimeTypeIdStructuredPostal = lookupMimeTypeId(StructuredPostal.CONTENT_ITEM_TYPE, db);
77178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
77278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
773b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
774b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onOpen(SQLiteDatabase db) {
7752a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        refreshDatabaseCaches(db);
77635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
77778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSyncState.onDatabaseOpened(db);
7781f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
7791f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        db.execSQL("ATTACH DATABASE ':memory:' AS " + DATABASE_PRESENCE + ";");
780e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS " + DATABASE_PRESENCE + "." + Tables.PRESENCE + " ("+
78182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.DATA_ID + " INTEGER PRIMARY KEY REFERENCES data(_id)," +
78282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.PROTOCOL + " INTEGER NOT NULL," +
78382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.CUSTOM_PROTOCOL + " TEXT," +
78482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.IM_HANDLE + " TEXT," +
78582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.IM_ACCOUNT + " TEXT," +
786a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                PresenceColumns.CONTACT_ID + " INTEGER REFERENCES contacts(_id)," +
787a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                PresenceColumns.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
78882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.PRESENCE + " INTEGER," +
789aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                StatusUpdates.CHAT_CAPABILITY + " INTEGER NOT NULL DEFAULT 0," +
79082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                "UNIQUE(" + StatusUpdates.PROTOCOL + ", " + StatusUpdates.CUSTOM_PROTOCOL
79182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                    + ", " + StatusUpdates.IM_HANDLE + ", " + StatusUpdates.IM_ACCOUNT + ")" +
7921f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        ");");
7931f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
794e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE INDEX IF NOT EXISTS " + DATABASE_PRESENCE + ".presenceIndex" + " ON "
7954dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov                + Tables.PRESENCE + " (" + PresenceColumns.RAW_CONTACT_ID + ");");
79609562b6c3a420ded0d02b9bd2290de2dbab9e304Vasu Nori        db.execSQL("CREATE INDEX IF NOT EXISTS " + DATABASE_PRESENCE + ".presenceIndex2" + " ON "
79709562b6c3a420ded0d02b9bd2290de2dbab9e304Vasu Nori                + Tables.PRESENCE + " (" + PresenceColumns.CONTACT_ID + ");");
798e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov
799e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS "
800aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + DATABASE_PRESENCE + "." + Tables.AGGREGATED_PRESENCE + " ("+
801e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov                AggregatedPresenceColumns.CONTACT_ID
802e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov                        + " INTEGER PRIMARY KEY REFERENCES contacts(_id)," +
803632248ae0053fa99b1f5b4cfaab3e55b7453fcb1Vasu Nori                StatusUpdates.PRESENCE + " INTEGER," +
804aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                StatusUpdates.CHAT_CAPABILITY + " INTEGER NOT NULL DEFAULT 0" +
805e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        ");");
806bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
807bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
808bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_deleted"
809bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEFORE DELETE ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
810bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
811bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + "   DELETE FROM " + Tables.AGGREGATED_PRESENCE
812bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + "     WHERE " + AggregatedPresenceColumns.CONTACT_ID + " = " +
813bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        "(SELECT " + PresenceColumns.CONTACT_ID +
814bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " FROM " + Tables.PRESENCE +
815bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " WHERE " + PresenceColumns.RAW_CONTACT_ID
816bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                + "=OLD." + PresenceColumns.RAW_CONTACT_ID +
817bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " AND NOT EXISTS" +
818bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                "(SELECT " + PresenceColumns.RAW_CONTACT_ID +
819bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " FROM " + Tables.PRESENCE +
820bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " WHERE " + PresenceColumns.CONTACT_ID
821bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                        + "=OLD." + PresenceColumns.CONTACT_ID +
822bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " AND " + PresenceColumns.RAW_CONTACT_ID
823bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                        + "!=OLD." + PresenceColumns.RAW_CONTACT_ID + "));"
824bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
825bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
826aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori        final String replaceAggregatePresenceSql =
827aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                "INSERT OR REPLACE INTO " + Tables.AGGREGATED_PRESENCE + "("
828093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + AggregatedPresenceColumns.CONTACT_ID + ", "
829093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.PRESENCE + ", "
830093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.CHAT_CAPABILITY + ")"
831093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                + " SELECT "
832093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + PresenceColumns.CONTACT_ID + ","
833093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.PRESENCE + ","
834093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.CHAT_CAPABILITY
835aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " FROM " + Tables.PRESENCE
836aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " WHERE "
837093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + " (ifnull(" + StatusUpdates.PRESENCE + ",0)  * 10 "
838093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                            + "+ ifnull(" + StatusUpdates.CHAT_CAPABILITY + ", 0))"
839093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + " = (SELECT "
840093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + "MAX (ifnull(" + StatusUpdates.PRESENCE + ",0)  * 10 "
841093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                                + "+ ifnull(" + StatusUpdates.CHAT_CAPABILITY + ", 0))"
842093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + " FROM " + Tables.PRESENCE
843093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + " WHERE " + PresenceColumns.CONTACT_ID
844093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                            + "=NEW." + PresenceColumns.CONTACT_ID
845093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + ")"
846093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                + " AND " + PresenceColumns.CONTACT_ID + "=NEW." + PresenceColumns.CONTACT_ID + ";";
847bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
848bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_inserted"
849bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " AFTER INSERT ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
850bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
851bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + replaceAggregatePresenceSql
852bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
853bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
854bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_updated"
855bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " AFTER UPDATE ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
856bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
857bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + replaceAggregatePresenceSql
858bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
859b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
860b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
861b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
862b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onCreate(SQLiteDatabase db) {
863069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee        Log.i(TAG, "Bootstrapping database version: " + DATABASE_VERSION);
864b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
86535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        mSyncState.createDatabase(db);
86635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
867b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // One row per group of contacts corresponding to the same person
868d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.CONTACTS + " (" +
869b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
870fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
871d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.PHOTO_ID + " INTEGER REFERENCES data(_id)," +
872f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                Contacts.PHOTO_FILE_ID + " INTEGER REFERENCES photo_files(_id)," +
873d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.CUSTOM_RINGTONE + " TEXT," +
874d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," +
875d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," +
876d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.LAST_TIME_CONTACTED + " INTEGER," +
877d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.STARRED + " INTEGER NOT NULL DEFAULT 0," +
878f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov                Contacts.HAS_PHONE_NUMBER + " INTEGER NOT NULL DEFAULT 0," +
8795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                Contacts.LOOKUP_KEY + " TEXT," +
880ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann                ContactsColumns.LAST_STATUS_UPDATE_ID + " INTEGER REFERENCES data(_id)" +
881b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
882b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
88354d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX contacts_has_phone_index ON " + Tables.CONTACTS + " (" +
88454d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                Contacts.HAS_PHONE_NUMBER +
88554d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
88654d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
887fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_name_raw_contact_id_index ON " + Tables.CONTACTS + " (" +
888fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID +
889fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
890fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
891b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Contacts table
8925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.RAW_CONTACTS + " (" +
8936cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
8946cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.ACCOUNT_NAME + " STRING DEFAULT NULL, " +
8956cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + " STRING DEFAULT NULL, " +
89643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                RawContacts.DATA_SET + " STRING DEFAULT NULL, " +
8976cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.SOURCE_ID + " TEXT," +
89897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                RawContacts.RAW_CONTACT_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
8996cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.VERSION + " INTEGER NOT NULL DEFAULT 1," +
90073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov                RawContacts.DIRTY + " INTEGER NOT NULL DEFAULT 0," +
90133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov                RawContacts.DELETED + " INTEGER NOT NULL DEFAULT 0," +
90254d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                RawContacts.CONTACT_ID + " INTEGER REFERENCES contacts(_id)," +
9036cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.AGGREGATION_MODE + " INTEGER NOT NULL DEFAULT " +
9046cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                        RawContacts.AGGREGATION_MODE_DEFAULT + "," +
9058e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov                RawContactsColumns.AGGREGATION_NEEDED + " INTEGER NOT NULL DEFAULT 1," +
9066cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.CUSTOM_RINGTONE + " TEXT," +
9076cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," +
9086cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," +
9096cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.LAST_TIME_CONTACTED + " INTEGER," +
91033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov                RawContacts.STARRED + " INTEGER NOT NULL DEFAULT 0," +
9115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_PRIMARY + " TEXT," +
9125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_ALTERNATIVE + " TEXT," +
9135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_SOURCE + " INTEGER NOT NULL DEFAULT " +
91425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov                        DisplayNameSources.UNDEFINED + "," +
9155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.PHONETIC_NAME + " TEXT," +
9165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.PHONETIC_NAME_STYLE + " TEXT," +
917de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                RawContacts.SORT_KEY_PRIMARY + " TEXT COLLATE " +
918de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                        ContactsProvider2.PHONEBOOK_COLLATOR_NAME + "," +
919de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                RawContacts.SORT_KEY_ALTERNATIVE + " TEXT COLLATE " +
920de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                        ContactsProvider2.PHONEBOOK_COLLATOR_NAME + "," +
921f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                RawContacts.NAME_VERIFIED + " INTEGER NOT NULL DEFAULT 0," +
9223cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC1 + " TEXT, " +
9233cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC2 + " TEXT, " +
9243cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC3 + " TEXT, " +
9253cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC4 + " TEXT " +
926b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
927b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
92854d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contacts_contact_id_index ON " + Tables.RAW_CONTACTS + " (" +
92954d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                RawContacts.CONTACT_ID +
93054d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
93154d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
9325f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contacts_source_id_index ON " + Tables.RAW_CONTACTS + " (" +
9335f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.SOURCE_ID + ", " +
9345f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + ", " +
9355f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.ACCOUNT_NAME +
9365f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        ");");
9375f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov
93843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        db.execSQL("CREATE INDEX raw_contacts_source_id_data_set_index ON " +
93943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                Tables.RAW_CONTACTS + " (" +
94043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                    RawContacts.SOURCE_ID + ", " +
94143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                    RawContacts.ACCOUNT_TYPE + ", " +
94243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                    RawContacts.ACCOUNT_NAME + ", " +
94343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                    RawContacts.DATA_SET +
94443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                ");");
94543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro
9463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann        db.execSQL("CREATE TABLE " + Tables.STREAM_ITEMS + " (" +
9473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann                StreamItems._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
9483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann                StreamItems.RAW_CONTACT_ID + " INTEGER NOT NULL, " +
9496802030a777c0c3ba1dc029c534cca4784260632Dave Santoro                StreamItems.RES_PACKAGE + " TEXT, " +
9500bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                StreamItems.RES_ICON + " TEXT, " +
9510bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                StreamItems.RES_LABEL + " TEXT, " +
9520bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                StreamItems.TEXT + " TEXT, " +
9533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann                StreamItems.TIMESTAMP + " INTEGER NOT NULL, " +
9540bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                StreamItems.COMMENTS + " TEXT, " +
9550bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                StreamItems.SYNC1 + " TEXT, " +
9560bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                StreamItems.SYNC2 + " TEXT, " +
9570bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                StreamItems.SYNC3 + " TEXT, " +
9580bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                StreamItems.SYNC4 + " TEXT, " +
9593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann                "FOREIGN KEY(" + StreamItems.RAW_CONTACT_ID + ") REFERENCES " +
9603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann                        Tables.RAW_CONTACTS + "(" + RawContacts._ID + "));");
9613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann
9623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann        db.execSQL("CREATE TABLE " + Tables.STREAM_ITEM_PHOTOS + " (" +
9633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann                StreamItemPhotos._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
9643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann                StreamItemPhotos.STREAM_ITEM_ID + " INTEGER NOT NULL, " +
9653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann                StreamItemPhotos.SORT_INDEX + " INTEGER, " +
9666802030a777c0c3ba1dc029c534cca4784260632Dave Santoro                StreamItemPhotos.PHOTO_FILE_ID + " INTEGER NOT NULL, " +
9670bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                StreamItemPhotos.SYNC1 + " TEXT, " +
9680bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                StreamItemPhotos.SYNC2 + " TEXT, " +
9690bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                StreamItemPhotos.SYNC3 + " TEXT, " +
9700bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                StreamItemPhotos.SYNC4 + " TEXT, " +
9713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann                "FOREIGN KEY(" + StreamItemPhotos.STREAM_ITEM_ID + ") REFERENCES " +
9723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann                        Tables.STREAM_ITEMS + "(" + StreamItems._ID + "));");
9733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann
974f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro        db.execSQL("CREATE TABLE " + Tables.PHOTO_FILES + " (" +
975f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                PhotoFiles._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
976f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                PhotoFiles.HEIGHT + " INTEGER NOT NULL, " +
977f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                PhotoFiles.WIDTH + " INTEGER NOT NULL, " +
978f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                PhotoFiles.FILESIZE + " INTEGER NOT NULL);");
979f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro
980f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        // TODO readd the index and investigate a controlled use of it
981f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//        db.execSQL("CREATE INDEX raw_contacts_agg_index ON " + Tables.RAW_CONTACTS + " (" +
982f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//                RawContactsColumns.AGGREGATION_NEEDED +
983f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//        ");");
9848e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov
985b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Package name mapping table
986ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PACKAGES + " (" +
987ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                PackagesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
988ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                PackagesColumns.PACKAGE + " TEXT NOT NULL" +
989b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
990b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
991ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // Mimetype mapping table
992ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.MIMETYPES + " (" +
993ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                MimetypesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
994ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                MimetypesColumns.MIMETYPE + " TEXT NOT NULL" +
995b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
996b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
99708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        // Mimetype table requires an index on mime type
99808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX mime_type ON " + Tables.MIMETYPES + " (" +
99908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov                MimetypesColumns.MIMETYPE +
100008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        ");");
100108768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
1002b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Public generic data table
1003b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.DATA + " (" +
1004b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
100567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                DataColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
1006b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                DataColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
100711944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                Data.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
100897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                Data.IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
1009f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.IS_PRIMARY + " INTEGER NOT NULL DEFAULT 0," +
1010f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.IS_SUPER_PRIMARY + " INTEGER NOT NULL DEFAULT 0," +
1011f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA_VERSION + " INTEGER NOT NULL DEFAULT 0," +
1012f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA1 + " TEXT," +
1013f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA2 + " TEXT," +
1014f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA3 + " TEXT," +
1015f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA4 + " TEXT," +
1016f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA5 + " TEXT," +
1017f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA6 + " TEXT," +
1018f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA7 + " TEXT," +
1019f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA8 + " TEXT," +
1020f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA9 + " TEXT," +
102167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA10 + " TEXT," +
102267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA11 + " TEXT," +
102367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA12 + " TEXT," +
102467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA13 + " TEXT," +
102567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA14 + " TEXT," +
10263cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.DATA15 + " TEXT," +
10273cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC1 + " TEXT, " +
10283cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC2 + " TEXT, " +
10293cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC3 + " TEXT, " +
10303cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC4 + " TEXT " +
1031b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
1032b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
103311944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        db.execSQL("CREATE INDEX data_raw_contact_id ON " + Tables.DATA + " (" +
103411944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                Data.RAW_CONTACT_ID +
103511944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        ");");
103611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
103711944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        /**
103811944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov         * For email lookup and similar queries.
103911944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov         */
1040f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov        db.execSQL("CREATE INDEX data_mimetype_data1_index ON " + Tables.DATA + " (" +
104111944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "," +
1042f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov                Data.DATA1 +
104311944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        ");");
104411944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
1045b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Private phone numbers table used for lookup
1046b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" +
1047f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.DATA_ID
1048892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        + " INTEGER REFERENCES data(_id) NOT NULL," +
10495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID
10505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
105136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL," +
105236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL" +
1053b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
1054b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1055b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" +
1056f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + "," +
1057f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
1058b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.DATA_ID +
1059b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
1060b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
106136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
106236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
106336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
106436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
106536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        ");");
106636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
1067d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_data_id_min_match_index ON " + Tables.PHONE_LOOKUP +
1068d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov                " (" + PhoneLookupColumns.DATA_ID + ", " + PhoneLookupColumns.MIN_MATCH + ");");
1069d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov
1070a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        // Private name/nickname table used for lookup
1071a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.NAME_LOOKUP + " (" +
107214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                NameLookupColumns.DATA_ID
107314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                        + " INTEGER REFERENCES data(_id) NOT NULL," +
10745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID
10755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
107611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                NameLookupColumns.NORMALIZED_NAME + " TEXT NOT NULL," +
107711944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                NameLookupColumns.NAME_TYPE + " INTEGER NOT NULL," +
107814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                "PRIMARY KEY ("
107914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                        + NameLookupColumns.DATA_ID + ", "
108011944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                        + NameLookupColumns.NORMALIZED_NAME + ", "
108111944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                        + NameLookupColumns.NAME_TYPE + ")" +
1082a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        ");");
1083a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
108414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        db.execSQL("CREATE INDEX name_lookup_raw_contact_id_index ON " + Tables.NAME_LOOKUP + " (" +
108514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID +
108614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        ");");
108714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov
1088b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.NICKNAME_LOOKUP + " (" +
1089b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + " TEXT," +
1090b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.CLUSTER + " TEXT" +
1091b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        ");");
1092b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
1093b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX nickname_lookup_index ON " + Tables.NICKNAME_LOOKUP + " (" +
1094b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + ", " +
1095b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.CLUSTER +
1096b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        ");");
1097b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
1098ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // Groups table
1099ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.GROUPS + " (" +
1100ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
110167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                GroupsColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
1102035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana                Groups.ACCOUNT_NAME + " STRING DEFAULT NULL, " +
1103035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana                Groups.ACCOUNT_TYPE + " STRING DEFAULT NULL, " +
110443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                Groups.DATA_SET + " STRING DEFAULT NULL, " +
1105ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups.SOURCE_ID + " TEXT," +
11069261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                Groups.VERSION + " INTEGER NOT NULL DEFAULT 1," +
110773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov                Groups.DIRTY + " INTEGER NOT NULL DEFAULT 0," +
1108ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups.TITLE + " TEXT," +
110967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Groups.TITLE_RES + " INTEGER," +
11100f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov                Groups.NOTES + " TEXT," +
11110f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov                Groups.SYSTEM_ID + " TEXT," +
111294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana                Groups.DELETED + " INTEGER NOT NULL DEFAULT 0," +
1113eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Groups.GROUP_VISIBLE + " INTEGER NOT NULL DEFAULT 0," +
1114ea547d55f864133861b2db44221ae0c2ac6c1a68Fred Quintana                Groups.SHOULD_SYNC + " INTEGER NOT NULL DEFAULT 1," +
1115dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                Groups.AUTO_ADD + " INTEGER NOT NULL DEFAULT 0," +
1116dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                Groups.FAVORITES + " INTEGER NOT NULL DEFAULT 0," +
1117c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                Groups.GROUP_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
11183cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC1 + " TEXT, " +
11193cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC2 + " TEXT, " +
11203cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC3 + " TEXT, " +
11213cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC4 + " TEXT " +
1122ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        ");");
1123ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
11245f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        db.execSQL("CREATE INDEX groups_source_id_index ON " + Tables.GROUPS + " (" +
11255f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.SOURCE_ID + ", " +
11265f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.ACCOUNT_TYPE + ", " +
11275f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.ACCOUNT_NAME +
11285f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        ");");
11295f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov
113043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        db.execSQL("CREATE INDEX groups_source_id_data_set_index ON " + Tables.GROUPS + " (" +
113143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                Groups.SOURCE_ID + ", " +
113243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                Groups.ACCOUNT_TYPE + ", " +
113343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                Groups.ACCOUNT_NAME + ", " +
113443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                Groups.DATA_SET +
113543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        ");");
113643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro
1137b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.AGGREGATION_EXCEPTIONS + " (" +
1138b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                AggregationExceptionColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
1139b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                AggregationExceptions.TYPE + " INTEGER NOT NULL, " +
11400c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1
11415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id), " +
11420c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2
11435ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id)" +
1144b0160a0bcf6d59eaa43fd501e124b95f873e0157Marc Blank        ");");
1145b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
1146b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index1 ON " +
1147b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                Tables.AGGREGATION_EXCEPTIONS + " (" +
11480c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1 + ", " +
11490c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2 +
1150b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        ");");
1151b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
1152b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index2 ON " +
1153b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                Tables.AGGREGATION_EXCEPTIONS + " (" +
11540c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2 + ", " +
11550c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1 +
1156b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        ");");
1157b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
1158eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.SETTINGS + " (" +
1159eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.ACCOUNT_NAME + " STRING NOT NULL," +
1160eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.ACCOUNT_TYPE + " STRING NOT NULL," +
1161f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                Settings.DATA_SET + " STRING," +
1162eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.UNGROUPED_VISIBLE + " INTEGER NOT NULL DEFAULT 0," +
1163f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                Settings.SHOULD_SYNC + " INTEGER NOT NULL DEFAULT 1" +
1164eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        ");");
1165eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey
11664394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.VISIBLE_CONTACTS + " (" +
11674394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
11684394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
11694394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
1170385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DEFAULT_DIRECTORY + " (" +
1171385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
1172385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        ");");
1173385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
1174e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        // The table for recent calls is here so we can do table joins
1175e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        // on people, phones, and calls all in one place.
1176e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.CALLS + " (" +
1177e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
1178e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.NUMBER + " TEXT," +
1179e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.DATE + " INTEGER," +
1180e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.DURATION + " INTEGER," +
1181e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.TYPE + " INTEGER," +
1182e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.NEW + " INTEGER," +
1183e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NAME + " TEXT," +
1184e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NUMBER_TYPE + " INTEGER," +
11852530512f639c4979fd7371c7dd25dd67e8118124Bai Tao                Calls.CACHED_NUMBER_LABEL + " TEXT," +
118659f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee                Calls.COUNTRY_ISO + " TEXT," +
118759f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee                Calls.VOICEMAIL_URI + " TEXT," +
1188b2197b235e3d96e7f70c24d548b7dac52dab88d8Flavio Lerda                Calls.IS_READ + " INTEGER," +
1189aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda                Calls.GEOCODED_LOCATION + " TEXT," +
11907a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda                Calls.CACHED_LOOKUP_URI + " TEXT," +
11917a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda                Calls.CACHED_MATCHED_NUMBER + " TEXT," +
11927a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda                Calls.CACHED_NORMALIZED_NUMBER + " TEXT," +
11937a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda                Calls.CACHED_PHOTO_ID + " INTEGER NOT NULL DEFAULT 0," +
119413ed28505ed1af4f0b4a6297c4c6840d91f10c8cFlavio Lerda                Calls.CACHED_FORMATTED_NUMBER + " TEXT," +
119559f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee                Voicemails._DATA + " TEXT," +
119659f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee                Voicemails.HAS_CONTENT + " INTEGER," +
119759f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee                Voicemails.MIME_TYPE + " TEXT," +
119859f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee                Voicemails.SOURCE_DATA + " TEXT," +
119959f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee                Voicemails.SOURCE_PACKAGE + " TEXT," +
120059f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee                Voicemails.STATE + " INTEGER" +
120159f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee        ");");
1202e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov
1203069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee        // Voicemail source status table.
1204069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee        db.execSQL("CREATE TABLE " + Tables.VOICEMAIL_STATUS + " (" +
1205069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee                VoicemailContract.Status._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
1206069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee                VoicemailContract.Status.SOURCE_PACKAGE + " TEXT UNIQUE NOT NULL," +
1207069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee                VoicemailContract.Status.SETTINGS_URI + " TEXT," +
1208069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee                VoicemailContract.Status.VOICEMAIL_ACCESS_URI + " TEXT," +
1209069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee                VoicemailContract.Status.CONFIGURATION_STATE + " INTEGER," +
1210069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee                VoicemailContract.Status.DATA_CHANNEL_STATE + " INTEGER," +
1211069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee                VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE + " INTEGER" +
1212069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee        ");");
1213069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee
1214b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Activities table
1215b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.ACTIVITIES + " (" +
1216b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
121767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                ActivitiesColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
1218b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                ActivitiesColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
1219b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.RAW_ID + " TEXT," +
1220499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.IN_REPLY_TO + " TEXT," +
12215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Activities.AUTHOR_CONTACT_ID +  " INTEGER REFERENCES raw_contacts(_id)," +
12225ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Activities.TARGET_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
1223b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.PUBLISHED + " INTEGER NOT NULL," +
1224499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.THREAD_PUBLISHED + " INTEGER NOT NULL," +
1225b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.TITLE + " TEXT NOT NULL," +
1226b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.SUMMARY + " TEXT," +
1227adb55c2d8295d300961d86a3605c8ddc469cd4a2Dmitri Plotnikov                Activities.LINK + " TEXT, " +
1228b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.THUMBNAIL + " BLOB" +
1229b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
1230b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1231a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.STATUS_UPDATES + " (" +
1232a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                StatusUpdatesColumns.DATA_ID + " INTEGER PRIMARY KEY REFERENCES data(_id)," +
12330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS + " TEXT," +
12340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_TIMESTAMP + " INTEGER," +
12350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_RES_PACKAGE + " TEXT, " +
12360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_LABEL + " INTEGER, " +
12370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_ICON + " INTEGER" +
1238a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        ");");
1239a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov
1240b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.PROPERTIES + " (" +
1241b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_KEY + " TEXT PRIMARY KEY, " +
1242b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_VALUE + " TEXT " +
1243b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ");");
1244b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
1245743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.ACCOUNTS + " (" +
124624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro                AccountsColumns.ACCOUNT_NAME + " TEXT, " +
124724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro                AccountsColumns.ACCOUNT_TYPE + " TEXT, " +
12485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                AccountsColumns.DATA_SET + " TEXT" +
1249743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        ");");
1250743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
1251743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // Allow contacts without any account to be created for now.  Achieve that
1252743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // by inserting a fake account with both type and name as NULL.
12535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " VALUES(NULL, NULL, NULL)");
1254743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
1255d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        createDirectoriesTable(db);
1256f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov        createSearchIndexTable(db);
1257d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
125846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        db.execSQL("CREATE TABLE " + Tables.DATA_USAGE_STAT + "(" +
125946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                DataUsageStatColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
126046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                DataUsageStatColumns.DATA_ID + " INTEGER NOT NULL, " +
126146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                DataUsageStatColumns.USAGE_TYPE_INT + " INTEGER NOT NULL DEFAULT 0, " +
126246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                DataUsageStatColumns.TIMES_USED + " INTEGER NOT NULL DEFAULT 0, " +
126346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                DataUsageStatColumns.LAST_TIME_USED + " INTERGER NOT NULL DEFAULT 0, " +
126446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                "FOREIGN KEY(" + DataUsageStatColumns.DATA_ID + ") REFERENCES "
126546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                        + Tables.DATA + "(" + Data._ID + ")" +
126646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        ");");
126746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        db.execSQL("CREATE UNIQUE INDEX data_usage_stat_index ON " +
126846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                Tables.DATA_USAGE_STAT + " (" +
126946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                DataUsageStatColumns.DATA_ID + ", " +
127046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                DataUsageStatColumns.USAGE_TYPE_INT +
127146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        ");");
127246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa
127372c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann        // When adding new tables, be sure to also add size-estimates in updateSqliteStats
1274a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        createContactsViews(db);
1275a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        createGroupsView(db);
1276fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        createContactsTriggers(db);
1277916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        createContactsIndexes(db);
12784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
1279a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        loadNicknameLookupTable(db);
1280a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
12815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        // Set sequence starts.
12825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        initializeAutoIncrementSequences(db);
12835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro
1284a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        // Add the legacy API support views, etc
1285a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        LegacyApiSupport.createDatabase(db);
1286a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
12872a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        if (mDatabaseOptimizationEnabled) {
12882a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // This will create a sqlite_stat1 table that is used for query optimization
12892a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            db.execSQL("ANALYZE;");
1290a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
12912a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            updateSqliteStats(db);
1292a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
12932a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // We need to close and reopen the database connection so that the stats are
12942a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // taken into account. Make a note of it and do the actual reopening in the
12952a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // getWritableDatabase method.
12962a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            mReopenDatabase = true;
12972a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        }
1298a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1299a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        ContentResolver.requestSync(null /* all accounts */,
1300a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                ContactsContract.AUTHORITY, new Bundle());
1301a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    }
1302a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
13035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro    protected void initializeAutoIncrementSequences(SQLiteDatabase db) {
13045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        // Default implementation does nothing.
13055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro    }
13065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro
1307d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    private void createDirectoriesTable(SQLiteDatabase db) {
1308d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DIRECTORIES + "(" +
1309d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
1310d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.PACKAGE_NAME + " TEXT NOT NULL," +
1311d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.DIRECTORY_AUTHORITY + " TEXT NOT NULL," +
1312d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.TYPE_RESOURCE_ID + " INTEGER," +
1313e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov                DirectoryColumns.TYPE_RESOURCE_NAME + " TEXT," +
1314d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.ACCOUNT_TYPE + " TEXT," +
1315d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.ACCOUNT_NAME + " TEXT," +
1316d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.DISPLAY_NAME + " TEXT, " +
1317d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.EXPORT_SUPPORT + " INTEGER NOT NULL" +
131897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                        " DEFAULT " + Directory.EXPORT_SUPPORT_NONE + "," +
131997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                Directory.SHORTCUT_SUPPORT + " INTEGER NOT NULL" +
13203d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        " DEFAULT " + Directory.SHORTCUT_SUPPORT_NONE + "," +
13213d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                Directory.PHOTO_SUPPORT + " INTEGER NOT NULL" +
13223d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        " DEFAULT " + Directory.PHOTO_SUPPORT_NONE +
1323d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        ");");
1324d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
13253d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        // Trigger a full scan of directories in the system
13263d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        setProperty(db, ContactDirectoryManager.PROPERTY_DIRECTORY_SCAN_COMPLETE, "0");
1327d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    }
1328d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
132905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov    public void createSearchIndexTable(SQLiteDatabase db) {
1330f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS " + Tables.SEARCH_INDEX);
1331f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov        db.execSQL("CREATE VIRTUAL TABLE " + Tables.SEARCH_INDEX
1332f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov                + " USING FTS4 ("
1333f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov                    + SearchIndexColumns.CONTACT_ID + " INTEGER REFERENCES contacts(_id) NOT NULL,"
1334f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov                    + SearchIndexColumns.CONTENT + " TEXT, "
1335155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov                    + SearchIndexColumns.NAME + " TEXT, "
1336f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov                    + SearchIndexColumns.TOKENS + " TEXT"
1337f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov                + ")");
1338f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov    }
1339f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov
13405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro    private void createContactsTriggers(SQLiteDatabase db) {
1341fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1342fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        /*
1343fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * Automatically delete Data rows when a raw contact is deleted.
1344fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         */
1345fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.RAW_CONTACTS + "_deleted;");
1346fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_deleted "
1347fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   BEFORE DELETE ON " + Tables.RAW_CONTACTS
1348fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1349fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.DATA
1350fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Data.RAW_CONTACT_ID
1351fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID + ";"
1352fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.AGGREGATION_EXCEPTIONS
1353fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + AggregationExceptions.RAW_CONTACT_ID1
1354fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID
1355fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "        OR " + AggregationExceptions.RAW_CONTACT_ID2
1356fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID + ";"
135735da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "   DELETE FROM " + Tables.VISIBLE_CONTACTS
135835da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
135935da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
136035da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
136135da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "           )=1;"
1362385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "   DELETE FROM " + Tables.DEFAULT_DIRECTORY
1363385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
1364385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
1365385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
1366385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "           )=1;"
1367fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.CONTACTS
1368fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
1369fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
1370fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
1371fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "           )=1;"
1372fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1373fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1374fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1375fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS contacts_times_contacted;");
13766c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        db.execSQL("DROP TRIGGER IF EXISTS raw_contacts_times_contacted;");
1377fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1378fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        /*
1379fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * Triggers that update {@link RawContacts#VERSION} when the contact is
1380fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * marked for deletion or any time a data row is inserted, updated or
1381fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * deleted.
1382fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         */
1383fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.RAW_CONTACTS + "_marked_deleted;");
1384fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_marked_deleted "
13857f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori                + "   AFTER UPDATE ON " + Tables.RAW_CONTACTS
1386fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1387fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1388fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET "
1389fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                +         RawContacts.VERSION + "=OLD." + RawContacts.VERSION + "+1 "
1390fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + RawContacts._ID
1391fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "       AND NEW." + RawContacts.DELETED + "!= OLD." + RawContacts.DELETED + ";"
1392fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1393fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1394fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.DATA + "_updated;");
13957f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_updated AFTER UPDATE ON " + Tables.DATA
1396fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1397fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.DATA
1398fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + Data.DATA_VERSION + "=OLD." + Data.DATA_VERSION + "+1 "
1399fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Data._ID + "=OLD." + Data._ID + ";"
1400fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1401fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + RawContacts.VERSION + "=" + RawContacts.VERSION + "+1 "
1402fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + Data.RAW_CONTACT_ID + ";"
1403fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1404fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1405fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.DATA + "_deleted;");
1406fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_deleted BEFORE DELETE ON " + Tables.DATA
1407fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1408fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1409fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + RawContacts.VERSION + "=" + RawContacts.VERSION + "+1 "
1410fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + Data.RAW_CONTACT_ID + ";"
1411fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.PHONE_LOOKUP
1412fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + PhoneLookupColumns.DATA_ID + "=OLD." + Data._ID + ";"
1413fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.STATUS_UPDATES
1414fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + StatusUpdatesColumns.DATA_ID + "=OLD." + Data._ID + ";"
1415fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.NAME_LOOKUP
1416fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + NameLookupColumns.DATA_ID + "=OLD." + Data._ID + ";"
1417fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1418fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1419fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1420fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.GROUPS + "_updated1;");
1421fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.GROUPS + "_updated1 "
14227f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori                + "   AFTER UPDATE ON " + Tables.GROUPS
1423fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1424fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.GROUPS
1425fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET "
1426fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                +         Groups.VERSION + "=OLD." + Groups.VERSION + "+1"
1427fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Groups._ID + "=OLD." + Groups._ID + ";"
1428fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
14293e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa
14303e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa        // Update DEFAULT_FILTER table per AUTO_ADD column update.
14313e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa        // See also upgradeToVersion411().
14323e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa        final String insertContactsWithoutAccount = (
14333e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                " INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
14343e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "     SELECT " + RawContacts.CONTACT_ID +
14353e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "     FROM " + Tables.RAW_CONTACTS +
14363e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "     WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL " +
14373e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "     AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL; ");
14383e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa        final String insertContactsWithAccountNoDefaultGroup = (
14393e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                " INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
14403e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "     SELECT " + RawContacts.CONTACT_ID +
14413e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "         FROM " + Tables.RAW_CONTACTS +
14423e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "     WHERE NOT EXISTS" +
14433e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "         (SELECT " + Groups._ID +
14443e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "             FROM " + Tables.GROUPS +
14453e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "             WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = " +
14463e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                        GroupsColumns.CONCRETE_ACCOUNT_NAME +
14473e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "             AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = " +
14483e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                        GroupsColumns.CONCRETE_ACCOUNT_TYPE +
14493e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "             AND " + Groups.AUTO_ADD + " != 0" + ");");
14503e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa        final String insertContactsWithAccountDefaultGroup = (
14513e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                " INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
14523e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "     SELECT " + RawContacts.CONTACT_ID +
14533e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "         FROM " + Tables.RAW_CONTACTS +
14543e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "     JOIN " + Tables.DATA +
14553e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "           ON (" + RawContactsColumns.CONCRETE_ID + "=" +
14563e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                        Data.RAW_CONTACT_ID + ")" +
145706c4a28bcdd9ca7c396de41b3bae5f6f43978fb5Daisuke Miyakawa                "     WHERE " + DataColumns.MIMETYPE_ID + "=" +
145806c4a28bcdd9ca7c396de41b3bae5f6f43978fb5Daisuke Miyakawa                    "(SELECT " + MimetypesColumns._ID + " FROM " + Tables.MIMETYPES +
145906c4a28bcdd9ca7c396de41b3bae5f6f43978fb5Daisuke Miyakawa                        " WHERE " + MimetypesColumns.MIMETYPE +
146006c4a28bcdd9ca7c396de41b3bae5f6f43978fb5Daisuke Miyakawa                            "='" + GroupMembership.CONTENT_ITEM_TYPE + "')" +
14613e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "     AND EXISTS" +
14623e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "         (SELECT " + Groups._ID +
14633e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "             FROM " + Tables.GROUPS +
14643e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "                 WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = " +
14653e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                        GroupsColumns.CONCRETE_ACCOUNT_NAME +
14663e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "                 AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = " +
14673e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                        GroupsColumns.CONCRETE_ACCOUNT_TYPE +
14683e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "                 AND " + Groups.AUTO_ADD + " != 0" + ");");
14693e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa
14703e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.GROUPS + "_auto_add_updated1;");
14713e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa        db.execSQL("CREATE TRIGGER " + Tables.GROUPS + "_auto_add_updated1 "
14723e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                + "   AFTER UPDATE OF " + Groups.AUTO_ADD + " ON " + Tables.GROUPS
14733e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                + " BEGIN "
14743e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                + "   DELETE FROM " + Tables.DEFAULT_DIRECTORY + ";"
14753e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                    + insertContactsWithoutAccount
14763e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                    + insertContactsWithAccountNoDefaultGroup
14773e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                    + insertContactsWithAccountDefaultGroup
14783e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                + " END");
1479fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov    }
1480fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
14815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro    private void createContactsIndexes(SQLiteDatabase db) {
1482916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
1483916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        db.execSQL("CREATE INDEX name_lookup_index ON " + Tables.NAME_LOOKUP + " (" +
1484916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.NORMALIZED_NAME + "," +
1485916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.NAME_TYPE + ", " +
1486916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID + ", " +
1487916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.DATA_ID +
1488916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        ");");
148904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
149004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS raw_contact_sort_key1_index");
149104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
149204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                RawContacts.SORT_KEY_PRIMARY +
149304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        ");");
149404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
149504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS raw_contact_sort_key2_index");
149604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key2_index ON " + Tables.RAW_CONTACTS + " (" +
149704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                RawContacts.SORT_KEY_ALTERNATIVE +
149804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        ");");
1499916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    }
1500916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov
15015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro    private void createContactsViews(SQLiteDatabase db) {
1502ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("DROP VIEW IF EXISTS " + Views.CONTACTS + ";");
1503ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("DROP VIEW IF EXISTS " + Views.DATA + ";");
1504ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_CONTACTS + ";");
1505a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_ENTITIES + ";");
1506a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.ENTITIES + ";");
1507ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("DROP VIEW IF EXISTS " + Views.DATA_USAGE_STAT + ";");
15089b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann        db.execSQL("DROP VIEW IF EXISTS " + Views.STREAM_ITEMS + ";");
1509a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
15104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String dataColumns =
15114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                Data.IS_PRIMARY + ", "
15124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.IS_SUPER_PRIMARY + ", "
15134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA_VERSION + ", "
15147cf50494501938f175d288077145acf49da8f171Daniel Lehmann                + DataColumns.CONCRETE_PACKAGE_ID + ","
15154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + PackagesColumns.PACKAGE + " AS " + Data.RES_PACKAGE + ","
15167cf50494501938f175d288077145acf49da8f171Daniel Lehmann                + DataColumns.CONCRETE_MIMETYPE_ID + ","
15174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + MimetypesColumns.MIMETYPE + " AS " + Data.MIMETYPE + ", "
151897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + Data.IS_READ_ONLY + ", "
15194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA1 + ", "
15204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA2 + ", "
15214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA3 + ", "
15224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA4 + ", "
15234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA5 + ", "
15244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA6 + ", "
15254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA7 + ", "
15264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA8 + ", "
15274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA9 + ", "
15284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA10 + ", "
15294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA11 + ", "
15304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA12 + ", "
15314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA13 + ", "
15324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA14 + ", "
15334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA15 + ", "
15344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC1 + ", "
15354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC2 + ", "
15364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC3 + ", "
15374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC4;
15384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
15394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String syncColumns =
15404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AS " + RawContacts.ACCOUNT_NAME + ","
15414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AS " + RawContacts.ACCOUNT_TYPE + ","
154243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                + RawContactsColumns.CONCRETE_DATA_SET + " AS " + RawContacts.DATA_SET + ","
154343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                + "(CASE WHEN " + RawContactsColumns.CONCRETE_DATA_SET + " IS NULL THEN "
154443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                        + RawContactsColumns.CONCRETE_ACCOUNT_TYPE
154543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                        + " ELSE " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + "||'/'||"
154643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                        + RawContactsColumns.CONCRETE_DATA_SET + " END) AS "
154743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                        + RawContacts.ACCOUNT_TYPE_AND_DATA_SET + ","
15484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SOURCE_ID + " AS " + RawContacts.SOURCE_ID + ","
154943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                + RawContactsColumns.CONCRETE_NAME_VERIFIED + " AS "
155043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                        + RawContacts.NAME_VERIFIED + ","
15514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_VERSION + " AS " + RawContacts.VERSION + ","
15524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DIRTY + " AS " + RawContacts.DIRTY + ","
15534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC1 + " AS " + RawContacts.SYNC1 + ","
15544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC2 + " AS " + RawContacts.SYNC2 + ","
15554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC3 + " AS " + RawContacts.SYNC3 + ","
15564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC4 + " AS " + RawContacts.SYNC4;
15574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
15583d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        String baseContactColumns =
15593d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                Contacts.HAS_PHONE_NUMBER + ", "
15603d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.NAME_RAW_CONTACT_ID + ", "
15613d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.LOOKUP_KEY + ", "
15623d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.PHOTO_ID + ", "
1563f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + Contacts.PHOTO_FILE_ID + ", "
15644c6e300d8cc5c62e74763454f61f9b10690cc618Dave Santoro                + "CAST(" + Clauses.CONTACT_VISIBLE + " AS INTEGER) AS "
15654c6e300d8cc5c62e74763454f61f9b10690cc618Dave Santoro                        + Contacts.IN_VISIBLE_GROUP + ", "
15663d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + ContactsColumns.LAST_STATUS_UPDATE_ID;
15673d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
15684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactOptionColumns =
15694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.CONCRETE_CUSTOM_RINGTONE
15704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.CUSTOM_RINGTONE + ","
15714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL
15724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.SEND_TO_VOICEMAIL + ","
15734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_LAST_TIME_CONTACTED
15744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.LAST_TIME_CONTACTED + ","
15754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_TIMES_CONTACTED
15764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.TIMES_CONTACTED + ","
15774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_STARRED
15784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.STARRED;
15794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
15805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String contactNameColumns =
15815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "name_raw_contact." + RawContacts.DISPLAY_NAME_SOURCE
15825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_SOURCE + ", "
15835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.DISPLAY_NAME_PRIMARY
15845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_PRIMARY + ", "
15855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.DISPLAY_NAME_ALTERNATIVE
15865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_ALTERNATIVE + ", "
15875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.PHONETIC_NAME
15885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.PHONETIC_NAME + ", "
15895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.PHONETIC_NAME_STYLE
15905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.PHONETIC_NAME_STYLE + ", "
15915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.SORT_KEY_PRIMARY
15925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.SORT_KEY_PRIMARY + ", "
15935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.SORT_KEY_ALTERNATIVE
15944394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        + " AS " + Contacts.SORT_KEY_ALTERNATIVE;
15955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
15964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String dataSelect = "SELECT "
15974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + Data._ID + ","
15984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.RAW_CONTACT_ID + ", "
1599fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + RawContacts.CONTACT_ID + ", "
16004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + syncColumns + ", "
16014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + dataColumns + ", "
16024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + contactOptionColumns + ", "
16035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + contactNameColumns + ", "
16043d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + baseContactColumns + ", "
1605f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + buildDisplayPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
16063d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_URI) + ", "
1607f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + buildThumbnailPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
16083d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_THUMBNAIL_URI) + ", "
16095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                + dbForProfile() + " AS " + RawContacts.RAW_CONTACT_IS_USER_PROFILE + ", "
16104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
16114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.DATA
1612a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.MIMETYPES + " ON ("
16134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1614a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " ON ("
16154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1616a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.CONTACTS + " ON ("
1617fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   RawContactsColumns.CONCRETE_CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID + ")"
1618fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1619fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")"
1620a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1621a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
16224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
16234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1624f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1625a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                        + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
16264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
1627ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("CREATE VIEW " + Views.DATA + " AS " + dataSelect);
16284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
16294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String rawContactOptionColumns =
16304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                RawContacts.CUSTOM_RINGTONE + ","
16314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.SEND_TO_VOICEMAIL + ","
16324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.LAST_TIME_CONTACTED + ","
16334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.TIMES_CONTACTED + ","
16344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.STARRED;
16354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
16364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String rawContactsSelect = "SELECT "
16374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + RawContacts._ID + ","
16384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.CONTACT_ID + ", "
16394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.AGGREGATION_MODE + ", "
164097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + RawContacts.RAW_CONTACT_IS_READ_ONLY + ", "
16414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.DELETED + ", "
16425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_SOURCE  + ", "
16435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_PRIMARY  + ", "
16445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_ALTERNATIVE  + ", "
16455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.PHONETIC_NAME  + ", "
16465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.PHONETIC_NAME_STYLE  + ", "
16475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.SORT_KEY_PRIMARY  + ", "
16485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.SORT_KEY_ALTERNATIVE + ", "
16495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                + dbForProfile() + " AS " + RawContacts.RAW_CONTACT_IS_USER_PROFILE + ", "
16504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + rawContactOptionColumns + ", "
16514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + syncColumns
16524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS;
16534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
1654ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("CREATE VIEW " + Views.RAW_CONTACTS + " AS " + rawContactsSelect);
16554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
16564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactsColumns =
16574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.CONCRETE_CUSTOM_RINGTONE
16584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.CUSTOM_RINGTONE + ", "
16595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + contactNameColumns + ", "
16603d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + baseContactColumns + ", "
16614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_LAST_TIME_CONTACTED
16624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.LAST_TIME_CONTACTED + ", "
16634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL
16644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.SEND_TO_VOICEMAIL + ", "
16654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_STARRED
16664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.STARRED + ", "
16674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_TIMES_CONTACTED
16683d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        + " AS " + Contacts.TIMES_CONTACTED;
16694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
16704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactsSelect = "SELECT "
16714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_ID + " AS " + Contacts._ID + ","
16723d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + contactsColumns + ", "
1673f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + buildDisplayPhotoUriAlias(ContactsColumns.CONCRETE_ID, Contacts.PHOTO_URI) + ", "
1674f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + buildThumbnailPhotoUriAlias(ContactsColumns.CONCRETE_ID,
167524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro                        Contacts.PHOTO_THUMBNAIL_URI) + ", "
16765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                + dbForProfile() + " AS " + Contacts.IS_USER_PROFILE
16774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.CONTACTS
1678fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1679fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")";
16804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
1681ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("CREATE VIEW " + Views.CONTACTS + " AS " + contactsSelect);
1682a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1683a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        String rawEntitiesSelect = "SELECT "
1684a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContacts.CONTACT_ID + ", "
1685a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DELETED + " AS " + RawContacts.DELETED + ","
1686a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + dataColumns + ", "
1687a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + syncColumns + ", "
1688a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC1 + ", "
1689a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC2 + ", "
1690a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC3 + ", "
1691a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC4 + ", "
1692a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + RawContacts._ID + ", "
1693a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + RawContacts.Entity.DATA_ID + ","
1694a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_STARRED + " AS " + RawContacts.STARRED + ","
16955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                + dbForProfile() + " AS " + RawContacts.RAW_CONTACT_IS_USER_PROFILE + ","
1696a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
1697a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS
1698a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.DATA + " ON ("
1699a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1700a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1701a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
1702a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.MIMETYPES + " ON ("
1703a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1704a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
1705a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1706a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1707a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
1708a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1709a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_ENTITIES + " AS "
1710a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + rawEntitiesSelect);
1711a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1712a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        String entitiesSelect = "SELECT "
1713a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + Contacts._ID + ", "
1714a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + RawContacts.CONTACT_ID + ", "
1715a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DELETED + " AS " + RawContacts.DELETED + ","
1716a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + dataColumns + ", "
1717a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + syncColumns + ", "
1718a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + contactsColumns + ", "
1719f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + buildDisplayPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
17203d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_URI) + ", "
1721f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + buildThumbnailPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
17223d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_THUMBNAIL_URI) + ", "
17235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro                + dbForProfile() + " AS " + Contacts.IS_USER_PROFILE + ", "
1724a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC1 + ", "
1725a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC2 + ", "
1726a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC3 + ", "
1727a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC4 + ", "
1728a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + Contacts.Entity.RAW_CONTACT_ID + ", "
1729a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + Contacts.Entity.DATA_ID + ","
1730a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
1731a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS
1732a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " JOIN " + Tables.CONTACTS + " ON ("
1733a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   RawContactsColumns.CONCRETE_CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID + ")"
1734a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1735a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")"
1736a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.DATA + " ON ("
1737a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1738a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1739a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
1740a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.MIMETYPES + " ON ("
1741a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1742a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
1743a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1744a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1745a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
1746a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1747a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.ENTITIES + " AS "
1748a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + entitiesSelect);
17492f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa
17502f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa        String dataUsageStatSelect = "SELECT "
17512f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                + DataUsageStatColumns.CONCRETE_ID + " AS " + DataUsageStatColumns._ID + ", "
17522f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                + DataUsageStatColumns.DATA_ID + ", "
17532f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + RawContacts.CONTACT_ID + ", "
17542f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                + MimetypesColumns.CONCRETE_MIMETYPE + " AS " + Data.MIMETYPE + ", "
17552f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                + DataUsageStatColumns.USAGE_TYPE_INT + ", "
17562f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                + DataUsageStatColumns.TIMES_USED + ", "
17572f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                + DataUsageStatColumns.LAST_TIME_USED
17582f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                + " FROM " + Tables.DATA_USAGE_STAT
17592f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                + " JOIN " + Tables.DATA + " ON ("
17602f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                +   DataColumns.CONCRETE_ID + "=" + DataUsageStatColumns.CONCRETE_DATA_ID + ")"
17612f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                + " JOIN " + Tables.RAW_CONTACTS + " ON ("
17622f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                +   RawContactsColumns.CONCRETE_ID + "=" + DataColumns.CONCRETE_RAW_CONTACT_ID
17632f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                    + " )"
17642f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                + " JOIN " + Tables.MIMETYPES + " ON ("
17652f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa                +   MimetypesColumns.CONCRETE_ID + "=" + DataColumns.CONCRETE_MIMETYPE_ID + ")";
17662f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa
1767ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("CREATE VIEW " + Views.DATA_USAGE_STAT + " AS " + dataUsageStatSelect);
17689b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann
17699b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann        String streamItemSelect = "SELECT " +
17709b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                StreamItemsColumns.CONCRETE_ID + ", " +
17719b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                ContactsColumns.CONCRETE_ID + " AS " + StreamItems.CONTACT_ID + ", " +
1772af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann                ContactsColumns.CONCRETE_LOOKUP_KEY +
1773af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann                        " AS " + StreamItems.CONTACT_LOOKUP_KEY + ", " +
17749b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                RawContactsColumns.CONCRETE_ACCOUNT_NAME + ", " +
17759b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                RawContactsColumns.CONCRETE_ACCOUNT_TYPE + ", " +
17769b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                RawContactsColumns.CONCRETE_DATA_SET + ", " +
17779b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                StreamItemsColumns.CONCRETE_RAW_CONTACT_ID +
17789b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                        " as " + StreamItems.RAW_CONTACT_ID + ", " +
17799b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                RawContactsColumns.CONCRETE_SOURCE_ID +
17809b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                        " as " + StreamItems.RAW_CONTACT_SOURCE_ID + ", " +
17819b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                StreamItemsColumns.CONCRETE_PACKAGE + ", " +
17829b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                StreamItemsColumns.CONCRETE_ICON + ", " +
17839b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                StreamItemsColumns.CONCRETE_LABEL + ", " +
17849b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                StreamItemsColumns.CONCRETE_TEXT + ", " +
17859b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                StreamItemsColumns.CONCRETE_TIMESTAMP + ", " +
17869b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                StreamItemsColumns.CONCRETE_COMMENTS + ", " +
17879b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                StreamItemsColumns.CONCRETE_SYNC1 + ", " +
17889b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                StreamItemsColumns.CONCRETE_SYNC2 + ", " +
17899b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                StreamItemsColumns.CONCRETE_SYNC3 + ", " +
17909b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                StreamItemsColumns.CONCRETE_SYNC4 +
17919b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                " FROM " + Tables.STREAM_ITEMS
17929b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                + " JOIN " + Tables.RAW_CONTACTS + " ON ("
17939b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                + StreamItemsColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID
17949b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                + ") JOIN " + Tables.CONTACTS + " ON ("
17959b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann                + RawContactsColumns.CONCRETE_CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID + ")";
17969b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann
17979b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann        db.execSQL("CREATE VIEW " + Views.STREAM_ITEMS + " AS " + streamItemSelect);
1798a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    }
17994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
1800f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro    private static String buildDisplayPhotoUriAlias(String contactIdColumn, String alias) {
1801f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro        return "(CASE WHEN " + Contacts.PHOTO_FILE_ID + " IS NULL THEN (CASE WHEN "
1802f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + Contacts.PHOTO_ID + " IS NULL"
1803f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + " OR " + Contacts.PHOTO_ID + "=0"
1804f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + " THEN NULL"
1805f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + " ELSE '" + Contacts.CONTENT_URI + "/'||"
1806f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                        + contactIdColumn + "|| '/" + Photo.CONTENT_DIRECTORY + "'"
1807f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + " END) ELSE '" + DisplayPhoto.CONTENT_URI + "/'||"
1808f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                        + Contacts.PHOTO_FILE_ID + " END)"
1809f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + " AS " + alias;
1810f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro    }
1811f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro
1812f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro    private static String buildThumbnailPhotoUriAlias(String contactIdColumn, String alias) {
1813f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro        return "(CASE WHEN "
1814f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + Contacts.PHOTO_ID + " IS NULL"
18152b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " OR " + Contacts.PHOTO_ID + "=0"
18162b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " THEN NULL"
1817f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                + " ELSE '" + Contacts.CONTENT_URI + "/'||"
18182b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                        + contactIdColumn + "|| '/" + Photo.CONTENT_DIRECTORY + "'"
18192b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " END)"
18202b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " AS " + alias;
18213d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
18223d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
18235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro    /**
18245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro     * Returns the value to be returned when querying the column indicating that the contact
18255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro     * or raw contact belongs to the user's personal profile.  Overridden in the profile
18265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro     * DB helper subclass.
18275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro     */
18285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro    protected int dbForProfile() {
18295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        return 0;
18305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro    }
18315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro
18325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro    private void createGroupsView(SQLiteDatabase db) {
1833ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("DROP VIEW IF EXISTS " + Views.GROUPS + ";");
183489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        String groupsColumns =
183589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                Groups.ACCOUNT_NAME + ","
183689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.ACCOUNT_TYPE + ","
183743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                + Groups.DATA_SET + ","
183843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                + "(CASE WHEN " + Groups.DATA_SET + " IS NULL THEN " + Groups.ACCOUNT_TYPE
183943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                    + " ELSE " + Groups.ACCOUNT_TYPE + "||" + Groups.DATA_SET + " END) AS "
184043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                    + Groups.ACCOUNT_TYPE_AND_DATA_SET + ","
184189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SOURCE_ID + ","
184289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.VERSION + ","
184389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.DIRTY + ","
184489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.TITLE + ","
184589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.TITLE_RES + ","
184689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.NOTES + ","
184789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYSTEM_ID + ","
184889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.DELETED + ","
184989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.GROUP_VISIBLE + ","
185089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SHOULD_SYNC + ","
1851dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + Groups.AUTO_ADD + ","
1852dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + Groups.FAVORITES + ","
1853c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                + Groups.GROUP_IS_READ_ONLY + ","
185489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC1 + ","
185589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC2 + ","
185689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC3 + ","
185789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC4 + ","
185889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + PackagesColumns.PACKAGE + " AS " + Groups.RES_PACKAGE;
185989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
186089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        String groupsSelect = "SELECT "
186189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + GroupsColumns.CONCRETE_ID + " AS " + Groups._ID + ","
186289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + groupsColumns
186389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + " FROM " + Tables.GROUPS_JOIN_PACKAGES;
186489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
1865ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("CREATE VIEW " + Views.GROUPS + " AS " + groupsSelect);
1866b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
1867b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1868b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
1869b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
187046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion < 99) {
187146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion
187246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana                    + ", data will be lost!");
187346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
187446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.CONTACTS + ";");
187546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.RAW_CONTACTS + ";");
187646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.PACKAGES + ";");
187746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.MIMETYPES + ";");
187846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.DATA + ";");
187946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.PHONE_LOOKUP + ";");
188046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.NAME_LOOKUP + ";");
188146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.NICKNAME_LOOKUP + ";");
188246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.GROUPS + ";");
188346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.ACTIVITIES + ";");
188446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.CALLS + ";");
188546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.SETTINGS + ";");
188646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.STATUS_UPDATES + ";");
188746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
188846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // TODO: we should not be dropping agg_exceptions and contact_options. In case that
188946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // table's schema changes, we should try to preserve the data, because it was entered
189046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // by the user and has never been synched to the server.
189146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.AGGREGATION_EXCEPTIONS + ";");
189246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
189346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            onCreate(db);
189446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            return;
189546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
1896f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
189746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion);
1898a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
189908e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        boolean upgradeViewsAndTriggers = false;
190004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        boolean upgradeNameLookup = false;
19018d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov        boolean upgradeLegacyApiSupport = false;
1902155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov        boolean upgradeSearchIndex = false;
190308e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov
190446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion == 99) {
190508e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
190646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            oldVersion++;
190746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
190846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
1909a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        if (oldVersion == 100) {
1910a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            db.execSQL("CREATE INDEX IF NOT EXISTS mimetypes_mimetype_index ON "
1911a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                    + Tables.MIMETYPES + " ("
1912a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                            + MimetypesColumns.MIMETYPE + ","
1913a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                            + MimetypesColumns._ID + ");");
1914a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            updateIndexStats(db, Tables.MIMETYPES,
1915a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                    "mimetypes_mimetype_index", "50 1 1");
1916a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
191708e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1918a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            oldVersion++;
1919a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        }
1920a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1921fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        if (oldVersion == 101) {
192208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1923fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov            oldVersion++;
1924fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        }
1925fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
192647ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov        if (oldVersion == 102) {
192708e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
192847ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov            oldVersion++;
192947ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov        }
193047ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov
193136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        if (oldVersion == 103) {
193208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1933bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey            oldVersion++;
1934bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey        }
1935bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey
193671037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov        if (oldVersion == 104 || oldVersion == 201) {
193771037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov            LegacyApiSupport.createSettingsTable(db);
193808e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
19393410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov            oldVersion++;
19403410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov        }
19413410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov
194271037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov        if (oldVersion == 105) {
19435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion202(db);
194404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            upgradeNameLookup = true;
19453410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov            oldVersion = 202;
194636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        }
194736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
1948fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        if (oldVersion == 202) {
19495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion203(db);
195008e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1951fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov            oldVersion++;
1952fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        }
1953fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
19549b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori        if (oldVersion == 203) {
195508e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
19569b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori            oldVersion++;
19579b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori        }
19589b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori
19595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (oldVersion == 204) {
19605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion205(db);
196108e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
19625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            oldVersion++;
19635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
19645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
1965f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        if (oldVersion == 205) {
1966f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            upgrateToVersion206(db);
1967f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1968f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            oldVersion++;
1969f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        }
1970f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov
197131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        if (oldVersion == 206) {
1972b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeToVersion300(db);
197334469970fb04b9b188b5430f592b0c956a6ea2aaDmitri Plotnikov            oldVersion = 300;
197431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
197531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
19766c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        if (oldVersion == 300) {
19776c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook            upgradeViewsAndTriggers = true;
19786c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook            oldVersion = 301;
19796c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        }
19806c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook
1981916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        if (oldVersion == 301) {
1982916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1983916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            oldVersion = 302;
1984916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        }
1985916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov
1986b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (oldVersion == 302) {
1987b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeEmailToVersion303(db);
1988b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeNicknameToVersion303(db);
1989b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            oldVersion = 303;
1990b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
1991b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
199208768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        if (oldVersion == 303) {
199308768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            upgradeToVersion304(db);
199408768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            oldVersion = 304;
199508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        }
199608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
1997f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        if (oldVersion == 304) {
1998f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee            upgradeNameLookup = true;
1999f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee            oldVersion = 305;
2000f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        }
2001f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee
200260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        if (oldVersion == 305) {
200360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            upgradeToVersion306(db);
200460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            oldVersion = 306;
200560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        }
200660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
2007b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        if (oldVersion == 306) {
2008b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            upgradeToVersion307(db);
2009b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            oldVersion = 307;
2010b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        }
2011b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
2012743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        if (oldVersion == 307) {
2013743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov            upgradeToVersion308(db);
2014743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov            oldVersion = 308;
2015743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        }
2016743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
201794c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        // Gingerbread upgrades
201894c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        if (oldVersion < 350) {
2019afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann            upgradeViewsAndTriggers = true;
202094c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            oldVersion = 351;
2021afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann        }
2022afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann
202394c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        if (oldVersion == 351) {
202494c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            upgradeNameLookup = true;
202594c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            oldVersion = 352;
202680d7871ca31d604cbfd857661d5300bb090076dbDaniel Lehmann        }
202780d7871ca31d604cbfd857661d5300bb090076dbDaniel Lehmann
20287da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        if (oldVersion == 352) {
20297da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            upgradeToVersion353(db);
20307da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            oldVersion = 353;
20317da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        }
20327da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
2033f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        // Honeycomb upgrades
2034f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        if (oldVersion < 400) {
2035dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana            upgradeViewsAndTriggers = true;
2036f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov            upgradeToVersion400(db);
2037f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov            oldVersion = 400;
2038dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        }
2039dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana
2040f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        if (oldVersion == 400) {
20414394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            upgradeViewsAndTriggers = true;
20424394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            upgradeToVersion401(db);
20434394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            oldVersion = 401;
20444394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        }
20454394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
2046d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        if (oldVersion == 401) {
2047d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov            upgradeToVersion402(db);
2048d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov            oldVersion = 402;
2049d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        }
2050d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
205197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        if (oldVersion == 402) {
205297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            upgradeViewsAndTriggers = true;
205397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            upgradeToVersion403(db);
205497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            oldVersion = 403;
205597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        }
205697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
2057a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        if (oldVersion == 403) {
2058a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov            upgradeViewsAndTriggers = true;
2059a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov            oldVersion = 404;
2060a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        }
2061a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
2062892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (oldVersion == 404) {
2063892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            upgradeViewsAndTriggers = true;
2064892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            upgradeToVersion405(db);
2065892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            oldVersion = 405;
2066892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
2067892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
20682530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        if (oldVersion == 405) {
20692530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            upgradeViewsAndTriggers = true;
20702530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            upgradeToVersion406(db);
20712530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            oldVersion = 406;
20722530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        }
20732530512f639c4979fd7371c7dd25dd67e8118124Bai Tao
2074cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov        if (oldVersion == 406) {
2075cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov            upgradeViewsAndTriggers = true;
2076cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov            oldVersion = 407;
2077cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov        }
2078cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov
2079385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        if (oldVersion == 407) {
2080d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            // Obsolete
2081385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            oldVersion = 408;
2082385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        }
2083385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
20843d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        if (oldVersion == 408) {
20853d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            upgradeViewsAndTriggers = true;
20863d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            upgradeToVersion409(db);
20873d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            oldVersion = 409;
20883d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        }
20893d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
20902b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        if (oldVersion == 409) {
20912b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov            upgradeViewsAndTriggers = true;
20922b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov            oldVersion = 410;
20932b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        }
20942b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov
2095d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        if (oldVersion == 410) {
2096d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            upgradeToVersion411(db);
2097d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            oldVersion = 411;
2098d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        }
2099d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov
21007da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        if (oldVersion == 411) {
21017da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            // Same upgrade as 353, only on Honeycomb devices
21027da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            upgradeToVersion353(db);
21037da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            oldVersion = 412;
21047da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        }
21057da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
2106e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov        if (oldVersion == 412) {
2107e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov            upgradeToVersion413(db);
2108e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov            oldVersion = 413;
2109e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov        }
2110e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov
211156f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee        if (oldVersion == 413) {
211256f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee            upgradeNameLookup = true;
211356f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee            oldVersion = 414;
211456f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee        }
211556f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee
2116c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        if (oldVersion == 414) {
2117c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            upgradeToVersion415(db);
2118c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            upgradeViewsAndTriggers = true;
2119c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            oldVersion = 415;
2120c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        }
2121c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov
2122d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov        if (oldVersion == 415) {
2123d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov            upgradeToVersion416(db);
2124d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov            oldVersion = 416;
2125d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov        }
2126d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov
21278d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov        if (oldVersion == 416) {
21288d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov            upgradeLegacyApiSupport = true;
21298d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov            oldVersion = 417;
21308d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov        }
21318d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov
2132f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov        // Honeycomb-MR1 upgrades
2133f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov        if (oldVersion < 500) {
2134155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov            upgradeSearchIndex = true;
2135f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov        }
2136f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov
2137197411a6cc3f81b94a34ca207f267d43d8548f04Dmitri Plotnikov        if (oldVersion < 501) {
2138155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov            upgradeSearchIndex = true;
2139197411a6cc3f81b94a34ca207f267d43d8548f04Dmitri Plotnikov            upgradeToVersion501(db);
2140197411a6cc3f81b94a34ca207f267d43d8548f04Dmitri Plotnikov            oldVersion = 501;
2141197411a6cc3f81b94a34ca207f267d43d8548f04Dmitri Plotnikov        }
2142197411a6cc3f81b94a34ca207f267d43d8548f04Dmitri Plotnikov
214392ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov        if (oldVersion < 502) {
2144155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov            upgradeSearchIndex = true;
214592ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov            upgradeToVersion502(db);
214692ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov            oldVersion = 502;
214792ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov        }
214892ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov
2149155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov        if (oldVersion < 503) {
2150155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov            upgradeSearchIndex = true;
2151155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov            oldVersion = 503;
2152155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov        }
2153155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov
215455e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        if (oldVersion < 504) {
215555e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            upgradeToVersion504(db);
215655e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            oldVersion = 504;
215755e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        }
215855e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov
215924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro        if (oldVersion < 600) {
216024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro            upgradeToVersion600(db);
216124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro            upgradeViewsAndTriggers = true;
216224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro            oldVersion = 600;
216324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro        }
216424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro
216546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        if (oldVersion < 601) {
216646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa            upgradeToVersion601(db);
216746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa            oldVersion = 601;
216846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        }
216946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa
217059f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee        if (oldVersion < 602) {
217159f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee            upgradeToVersion602(db);
217259f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee            oldVersion = 602;
217359f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee        }
217459f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee
21752f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa        if (oldVersion < 603) {
21762f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa            upgradeViewsAndTriggers = true;
21772f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa            oldVersion = 603;
21782f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa        }
21792f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa
2180069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee        if (oldVersion < 604) {
2181069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee            upgradeToVersion604(db);
2182069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee            oldVersion = 604;
2183069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee        }
2184069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee
21853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann        if (oldVersion < 605) {
2186f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro            upgradeViewsAndTriggers = true;
21873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann            upgradeToVersion605(db);
21883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann            oldVersion = 605;
21893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann        }
21903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann
2191ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        if (oldVersion < 606) {
2192ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann            upgradeViewsAndTriggers = true;
2193ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann            upgradeLegacyApiSupport = true;
2194ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann            upgradeToVersion606(db);
2195ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann            oldVersion = 606;
2196ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        }
2197ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann
21981cdfc9dacc136e99d3c0bc5b4212bc3c973be337Daniel Lehmann        if (oldVersion < 607) {
21991cdfc9dacc136e99d3c0bc5b4212bc3c973be337Daniel Lehmann            upgradeViewsAndTriggers = true;
22001cdfc9dacc136e99d3c0bc5b4212bc3c973be337Daniel Lehmann            upgradeToVersion607(db);
22011cdfc9dacc136e99d3c0bc5b4212bc3c973be337Daniel Lehmann            oldVersion = 607;
22021cdfc9dacc136e99d3c0bc5b4212bc3c973be337Daniel Lehmann        }
22031cdfc9dacc136e99d3c0bc5b4212bc3c973be337Daniel Lehmann
2204f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro        if (oldVersion < 608) {
2205f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro            upgradeViewsAndTriggers = true;
2206f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro            upgradeToVersion608(db);
2207f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro            oldVersion = 608;
2208f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro        }
2209f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro
22106802030a777c0c3ba1dc029c534cca4784260632Dave Santoro        if (oldVersion < 609) {
22116802030a777c0c3ba1dc029c534cca4784260632Dave Santoro            upgradeToVersion609(db);
22126802030a777c0c3ba1dc029c534cca4784260632Dave Santoro            oldVersion = 609;
22136802030a777c0c3ba1dc029c534cca4784260632Dave Santoro        }
22146802030a777c0c3ba1dc029c534cca4784260632Dave Santoro
2215b2197b235e3d96e7f70c24d548b7dac52dab88d8Flavio Lerda        if (oldVersion < 610) {
2216b2197b235e3d96e7f70c24d548b7dac52dab88d8Flavio Lerda            upgradeToVersion610(db);
2217b2197b235e3d96e7f70c24d548b7dac52dab88d8Flavio Lerda            oldVersion = 610;
2218b2197b235e3d96e7f70c24d548b7dac52dab88d8Flavio Lerda        }
2219b2197b235e3d96e7f70c24d548b7dac52dab88d8Flavio Lerda
222043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        if (oldVersion < 611) {
222143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro            upgradeViewsAndTriggers = true;
222243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro            upgradeToVersion611(db);
222343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro            oldVersion = 611;
222443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        }
2225f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro
2226aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda        if (oldVersion < 612) {
2227aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda            upgradeViewsAndTriggers = true;
2228aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda            upgradeToVersion612(db);
2229aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda            oldVersion = 612;
2230aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda        }
2231aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda
22320bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        if (oldVersion < 613) {
22330bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann            upgradeToVersion613(db);
22340bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann            oldVersion = 613;
22350bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        }
22360bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann
22379b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann        if (oldVersion < 614) {
22389b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann            // this creates the view "view_stream_items"
22399b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann            upgradeViewsAndTriggers = true;
22409b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann            oldVersion = 614;
22419b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann        }
22429b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann
22437a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda        if (oldVersion < 615) {
22447a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda            upgradeToVersion615(db);
22457a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda            oldVersion = 615;
22467a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda        }
22477a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda
2248af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann        if (oldVersion < 616) {
2249af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann            // this updates the "view_stream_items" view
2250af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann            upgradeViewsAndTriggers = true;
2251af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann            oldVersion = 616;
2252af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann        }
2253af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann
22545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        if (oldVersion < 617) {
22555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro            // This version upgrade obsoleted the profile_raw_contact_id field of the Accounts
22565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro            // table, but we aren't removing the column because it is very little data (and not
22575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro            // referenced anymore).  We do need to upgrade the views to handle the simplified
22585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro            // per-database "is profile" columns.
22595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro            upgradeViewsAndTriggers = true;
22605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro            oldVersion = 617;
22615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        }
22625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro
2263f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro        if (oldVersion < 618) {
2264f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro            upgradeToVersion618(db);
2265f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro            oldVersion = 618;
2266f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro        }
2267f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro
22687cf50494501938f175d288077145acf49da8f171Daniel Lehmann        if (oldVersion < 619) {
22697cf50494501938f175d288077145acf49da8f171Daniel Lehmann            upgradeViewsAndTriggers = true;
22707cf50494501938f175d288077145acf49da8f171Daniel Lehmann            oldVersion = 619;
22717cf50494501938f175d288077145acf49da8f171Daniel Lehmann        }
22727cf50494501938f175d288077145acf49da8f171Daniel Lehmann
22734c6e300d8cc5c62e74763454f61f9b10690cc618Dave Santoro        if (oldVersion < 620) {
22744c6e300d8cc5c62e74763454f61f9b10690cc618Dave Santoro            upgradeViewsAndTriggers = true;
22754c6e300d8cc5c62e74763454f61f9b10690cc618Dave Santoro            oldVersion = 620;
22764c6e300d8cc5c62e74763454f61f9b10690cc618Dave Santoro        }
22774c6e300d8cc5c62e74763454f61f9b10690cc618Dave Santoro
22788f79445f450755858a88e8a5a0e14d81a0b9ff87Daisuke Miyakawa        if (oldVersion < 621) {
22798f79445f450755858a88e8a5a0e14d81a0b9ff87Daisuke Miyakawa            upgradeSearchIndex = true;
22808f79445f450755858a88e8a5a0e14d81a0b9ff87Daisuke Miyakawa            oldVersion = 621;
22818f79445f450755858a88e8a5a0e14d81a0b9ff87Daisuke Miyakawa        }
22828f79445f450755858a88e8a5a0e14d81a0b9ff87Daisuke Miyakawa
228313ed28505ed1af4f0b4a6297c4c6840d91f10c8cFlavio Lerda        if (oldVersion < 622) {
228413ed28505ed1af4f0b4a6297c4c6840d91f10c8cFlavio Lerda            upgradeToVersion622(db);
228513ed28505ed1af4f0b4a6297c4c6840d91f10c8cFlavio Lerda            oldVersion = 622;
228613ed28505ed1af4f0b4a6297c4c6840d91f10c8cFlavio Lerda        }
228713ed28505ed1af4f0b4a6297c4c6840d91f10c8cFlavio Lerda
2288d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann        if (oldVersion < 623) {
2289d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann            // change FTS to normalize names using collation key
2290d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann            upgradeSearchIndex = true;
2291d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann            oldVersion = 623;
2292d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann        }
2293d1746e09bc7739f3d1449cececc66d5045ada498Daniel Lehmann
229472c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann        if (oldVersion < 624) {
229572c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            // Upgraded the sqlite index stats
229672c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            upgradeViewsAndTriggers = true;
229772c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            oldVersion = 624;
229872c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann        }
229972c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann
2300f5f038faf7f3ef460e1c11028d467954840e5f6fMakoto Onuki        if (oldVersion < 625) {
2301f5f038faf7f3ef460e1c11028d467954840e5f6fMakoto Onuki            // Fix for search for hyphenated names
2302f5f038faf7f3ef460e1c11028d467954840e5f6fMakoto Onuki            upgradeSearchIndex = true;
2303f5f038faf7f3ef460e1c11028d467954840e5f6fMakoto Onuki            oldVersion = 625;
2304f5f038faf7f3ef460e1c11028d467954840e5f6fMakoto Onuki        }
2305f5f038faf7f3ef460e1c11028d467954840e5f6fMakoto Onuki
230608e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        if (upgradeViewsAndTriggers) {
230708e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createContactsViews(db);
230808e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createGroupsView(db);
230908e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createContactsTriggers(db);
2310916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            createContactsIndexes(db);
2311916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            updateSqliteStats(db);
23128d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov            upgradeLegacyApiSupport = true;
2313916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            mReopenDatabase = true;
231408e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        }
231508e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov
23168d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov        if (upgradeLegacyApiSupport) {
23178d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov            LegacyApiSupport.createViews(db);
23188d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov        }
23198d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov
232004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (upgradeNameLookup) {
232104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            rebuildNameLookup(db);
232204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
232304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
2324155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov        if (upgradeSearchIndex) {
23252c4caaa35be9f8909e8eee26142c4747bbf65aacDaniel Lehmann            createSearchIndexTable(db);
2326155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov            setProperty(db, SearchIndexManager.PROPERTY_SEARCH_INDEX_VERSION, "0");
2327155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov        }
2328155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov
232946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion != newVersion) {
233046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            throw new IllegalStateException(
233146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana                    "error upgrading the database to version " + newVersion);
233246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
2333b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
2334b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
23355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion202(SQLiteDatabase db) {
233636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL(
233736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "ALTER TABLE " + Tables.PHONE_LOOKUP +
233836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " ADD " + PhoneLookupColumns.MIN_MATCH + " TEXT;");
233936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
234036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
234136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
234236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
234336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
234436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        ");");
234536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
234636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        updateIndexStats(db, Tables.PHONE_LOOKUP,
234736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "phone_lookup_min_match_index", "10000 2 2 1");
234836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
234936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        SQLiteStatement update = db.compileStatement(
235036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "UPDATE " + Tables.PHONE_LOOKUP +
235136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " SET " + PhoneLookupColumns.MIN_MATCH + "=?" +
235236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " WHERE " + PhoneLookupColumns.DATA_ID + "=?");
235336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
235436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        // Populate the new column
235536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        Cursor c = db.query(Tables.PHONE_LOOKUP + " JOIN " + Tables.DATA +
235636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " ON (" + PhoneLookupColumns.DATA_ID + "=" + DataColumns.CONCRETE_ID + ")",
235736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                new String[]{Data._ID, Phone.NUMBER}, null, null, null, null, null);
235836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        try {
235936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            while (c.moveToNext()) {
236036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                long dataId = c.getLong(0);
236136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                String number = c.getString(1);
236236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                if (!TextUtils.isEmpty(number)) {
236336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.bindString(1, PhoneNumberUtils.toCallerIDMinMatch(number));
236436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.bindLong(2, dataId);
236536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.execute();
236636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                }
236736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            }
236836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        } finally {
236936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            c.close();
237036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        }
237136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    }
237236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
23735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion203(SQLiteDatabase db) {
2374758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // Garbage-collect first. A bug in Eclair was sometimes leaving
2375758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // raw_contacts in the database that no longer had contacts associated
2376758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // with them.  To avoid failures during this database upgrade, drop
2377758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // the orphaned raw_contacts.
2378758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        db.execSQL(
2379758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                "DELETE FROM raw_contacts" +
2380758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                " WHERE contact_id NOT NULL" +
2381758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                " AND contact_id NOT IN (SELECT _id FROM contacts)");
2382758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov
2383fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
2384fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "ALTER TABLE " + Tables.CONTACTS +
2385fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " ADD " + Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)");
2386fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
2387fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "ALTER TABLE " + Tables.RAW_CONTACTS +
23884394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " ADD contact_in_visible_group INTEGER NOT NULL DEFAULT 0");
2389fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
2390fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // For each Contact, find the RawContact that contributed the display name
2391fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
2392fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
2393fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.NAME_RAW_CONTACT_ID + "=(" +
2394fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " SELECT " + RawContacts._ID +
2395fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.RAW_CONTACTS +
2396fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
2397fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " AND " + RawContactsColumns.CONCRETE_DISPLAY_NAME + "=" +
2398fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                                Tables.CONTACTS + "." + Contacts.DISPLAY_NAME +
2399fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " ORDER BY " + RawContacts._ID +
2400fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " LIMIT 1)"
2401fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
2402fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
2403fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_name_raw_contact_id_index ON " + Tables.CONTACTS + " (" +
2404fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID +
2405fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
2406fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
2407fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // If for some unknown reason we missed some names, let's make sure there are
2408fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // no contacts without a name, picking a raw contact "at random".
2409fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
2410fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
2411fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.NAME_RAW_CONTACT_ID + "=(" +
2412fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " SELECT " + RawContacts._ID +
2413fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.RAW_CONTACTS +
2414fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
2415fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " ORDER BY " + RawContacts._ID +
2416fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " LIMIT 1)" +
2417fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " WHERE " + Contacts.NAME_RAW_CONTACT_ID + " IS NULL"
2418fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
2419fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
2420fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // Wipe out DISPLAY_NAME on the Contacts table as it is no longer in use.
2421fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
2422fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
2423fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.DISPLAY_NAME + "=NULL"
2424fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
2425fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
2426fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // Copy the IN_VISIBLE_GROUP flag down to all raw contacts to allow
2427fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // indexing on (display_name, in_visible_group)
2428fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
2429fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.RAW_CONTACTS +
24304394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " SET contact_in_visible_group=(" +
2431fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        "SELECT " + Contacts.IN_VISIBLE_GROUP +
2432fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.CONTACTS +
2433bcbd6a5cdd2d1aa6531c592428dc20e0282486c3Dmitri Plotnikov                        " WHERE " + Contacts._ID + "=" + RawContacts.CONTACT_ID + ")" +
2434bcbd6a5cdd2d1aa6531c592428dc20e0282486c3Dmitri Plotnikov                " WHERE " + RawContacts.CONTACT_ID + " NOT NULL"
2435fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
2436fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
2437fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
24384394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
2439fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                RawContactsColumns.DISPLAY_NAME + " COLLATE LOCALIZED ASC" +
2440fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
2441fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
2442fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("DROP INDEX contacts_visible_index");
2443fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_visible_index ON " + Tables.CONTACTS + " (" +
2444fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.IN_VISIBLE_GROUP +
2445fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
2446fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov    }
2447fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
24485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion205(SQLiteDatabase db) {
24495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
24505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.DISPLAY_NAME_ALTERNATIVE + " TEXT;");
24515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
24525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.PHONETIC_NAME + " TEXT;");
24535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
24545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.PHONETIC_NAME_STYLE + " INTEGER;");
24555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
2456de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " ADD " + RawContacts.SORT_KEY_PRIMARY
2457de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " TEXT COLLATE " + ContactsProvider2.PHONEBOOK_COLLATOR_NAME + ";");
24585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
2459de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " ADD " + RawContacts.SORT_KEY_ALTERNATIVE
2460de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " TEXT COLLATE " + ContactsProvider2.PHONEBOOK_COLLATOR_NAME + ";");
24615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
24625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        final Locale locale = Locale.getDefault();
24635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
246451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        NameSplitter splitter = createNameSplitter();
24655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
24665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement rawContactUpdate = db.compileStatement(
24675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.RAW_CONTACTS +
24685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
24695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.DISPLAY_NAME_PRIMARY + "=?," +
24705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," +
24715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.PHONETIC_NAME + "=?," +
24725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.PHONETIC_NAME_STYLE + "=?," +
24735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.SORT_KEY_PRIMARY + "=?," +
24745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.SORT_KEY_ALTERNATIVE + "=?" +
24755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + RawContacts._ID + "=?");
24765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
24775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        upgradeStructuredNamesToVersion205(db, rawContactUpdate, splitter);
24785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        upgradeOrganizationsToVersion205(db, rawContactUpdate, splitter);
24795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
24805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("DROP INDEX raw_contact_sort_key1_index");
24815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
24824394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
24835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.SORT_KEY_PRIMARY +
24845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        ");");
24855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
24865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key2_index ON " + Tables.RAW_CONTACTS + " (" +
24874394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
24885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.SORT_KEY_ALTERNATIVE +
24895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        ");");
24905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
24915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
24925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private interface StructName205Query {
24935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String TABLE = Tables.DATA_JOIN_RAW_CONTACTS;
24945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
24955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String COLUMNS[] = {
24965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.CONCRETE_ID,
24975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Data.RAW_CONTACT_ID,
24985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_SOURCE,
24995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_PRIMARY,
25005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PREFIX,
25015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.GIVEN_NAME,
25025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.MIDDLE_NAME,
25035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.FAMILY_NAME,
25045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.SUFFIX,
25055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_FAMILY_NAME,
25065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_MIDDLE_NAME,
25075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_GIVEN_NAME,
25085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        };
25095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
25105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int ID = 0;
25115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int RAW_CONTACT_ID = 1;
25125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int DISPLAY_NAME_SOURCE = 2;
25135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int DISPLAY_NAME = 3;
25145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PREFIX = 4;
25155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int GIVEN_NAME = 5;
25165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int MIDDLE_NAME = 6;
25175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int FAMILY_NAME = 7;
25185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int SUFFIX = 8;
25195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_FAMILY_NAME = 9;
25205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_MIDDLE_NAME = 10;
25215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_GIVEN_NAME = 11;
25225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
25235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
25245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeStructuredNamesToVersion205(SQLiteDatabase db,
25255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement rawContactUpdate, NameSplitter splitter) {
25265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
25275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        // Process structured names to detect the style of the full name and phonetic name
25285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
25295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        long mMimeType;
25305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
25315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            mMimeType = DatabaseUtils.longForQuery(db,
25325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    "SELECT " + MimetypesColumns._ID +
25335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    " FROM " + Tables.MIMETYPES +
25345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    " WHERE " + MimetypesColumns.MIMETYPE
25355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                            + "='" + StructuredName.CONTENT_ITEM_TYPE + "'", null);
25365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } catch (SQLiteDoneException e) {
25375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            // No structured names in the database
25385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            return;
25395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
25405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
25415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement structuredNameUpdate = db.compileStatement(
25425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.DATA +
25435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
25445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.FULL_NAME_STYLE + "=?," +
25455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.DISPLAY_NAME + "=?," +
25465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.PHONETIC_NAME_STYLE + "=?" +
25475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + Data._ID + "=?");
25485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
25495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        NameSplitter.Name name = new NameSplitter.Name();
25505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        StringBuilder sb = new StringBuilder();
25515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        Cursor cursor = db.query(StructName205Query.TABLE,
25525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructName205Query.COLUMNS,
25535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=" + mMimeType, null, null, null, null);
25545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
25555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            while (cursor.moveToNext()) {
25565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long dataId = cursor.getLong(StructName205Query.ID);
25575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long rawContactId = cursor.getLong(StructName205Query.RAW_CONTACT_ID);
25585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                int displayNameSource = cursor.getInt(StructName205Query.DISPLAY_NAME_SOURCE);
25595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String displayName = cursor.getString(StructName205Query.DISPLAY_NAME);
25605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
25615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.clear();
25625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.prefix = cursor.getString(StructName205Query.PREFIX);
25635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.givenNames = cursor.getString(StructName205Query.GIVEN_NAME);
25645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.middleName = cursor.getString(StructName205Query.MIDDLE_NAME);
25655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.familyName = cursor.getString(StructName205Query.FAMILY_NAME);
25665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.suffix = cursor.getString(StructName205Query.SUFFIX);
25675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticFamilyName = cursor.getString(StructName205Query.PHONETIC_FAMILY_NAME);
25685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticMiddleName = cursor.getString(StructName205Query.PHONETIC_MIDDLE_NAME);
25695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticGivenName = cursor.getString(StructName205Query.PHONETIC_GIVEN_NAME);
25705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
25715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                upgradeNameToVersion205(dataId, rawContactId, displayNameSource, displayName, name,
25725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        structuredNameUpdate, rawContactUpdate, splitter, sb);
25735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
25745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } finally {
25755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            cursor.close();
25765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
25775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
25785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
25795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeNameToVersion205(long dataId, long rawContactId, int displayNameSource,
25805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String currentDisplayName, NameSplitter.Name name,
25815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement structuredNameUpdate, SQLiteStatement rawContactUpdate,
25825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            NameSplitter splitter, StringBuilder sb) {
25835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
25845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        splitter.guessNameStyle(name);
2585ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        int unadjustedFullNameStyle = name.fullNameStyle;
25865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        name.fullNameStyle = splitter.getAdjustedFullNameStyle(name.fullNameStyle);
258755e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        String displayName = splitter.join(name, true, true);
25885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
2589ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        // Don't update database with the adjusted fullNameStyle as it is locale
2590ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        // related
2591ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        structuredNameUpdate.bindLong(1, unadjustedFullNameStyle);
25925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        DatabaseUtils.bindObjectToProgram(structuredNameUpdate, 2, displayName);
25935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.bindLong(3, name.phoneticNameStyle);
25945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.bindLong(4, dataId);
25955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.execute();
25965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
25975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (displayNameSource == DisplayNameSources.STRUCTURED_NAME) {
259855e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            String displayNameAlternative = splitter.join(name, false, false);
25995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String phoneticName = splitter.joinPhoneticName(name);
26005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String sortKey = null;
26015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String sortKeyAlternative = null;
26025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            if (phoneticName != null) {
26045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKey = sortKeyAlternative = phoneticName;
2605ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao            } else if (name.fullNameStyle == FullNameStyle.CHINESE ||
2606ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                    name.fullNameStyle == FullNameStyle.CJK) {
2607ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                sortKey = sortKeyAlternative = ContactLocaleUtils.getIntance()
2608ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                        .getSortKey(displayName, name.fullNameStyle);
26095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
26105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            if (sortKey == null) {
26125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKey = displayName;
26135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKeyAlternative = displayNameAlternative;
26145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
26155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            updateRawContact205(rawContactUpdate, rawContactId, displayName,
26175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    displayNameAlternative, name.phoneticNameStyle, phoneticName, sortKey,
26185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    sortKeyAlternative);
26195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
26205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
26215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private interface Organization205Query {
26235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String TABLE = Tables.DATA_JOIN_RAW_CONTACTS;
26245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String COLUMNS[] = {
26265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.CONCRETE_ID,
26275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Data.RAW_CONTACT_ID,
26285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Organization.COMPANY,
26295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Organization.PHONETIC_NAME,
26305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        };
26315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int ID = 0;
26335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int RAW_CONTACT_ID = 1;
26345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int COMPANY = 2;
26355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_NAME = 3;
26365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
26375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeOrganizationsToVersion205(SQLiteDatabase db,
26395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement rawContactUpdate, NameSplitter splitter) {
2640b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeType = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
26415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement organizationUpdate = db.compileStatement(
26435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.DATA +
26445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
26455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        Organization.PHONETIC_NAME_STYLE + "=?" +
26465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + Data._ID + "=?");
26475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        Cursor cursor = db.query(Organization205Query.TABLE, Organization205Query.COLUMNS,
2649b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=" + mimeType + " AND "
26505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + RawContacts.DISPLAY_NAME_SOURCE + "=" + DisplayNameSources.ORGANIZATION,
26515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                null, null, null, null);
26525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
26535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            while (cursor.moveToNext()) {
26545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long dataId = cursor.getLong(Organization205Query.ID);
26555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long rawContactId = cursor.getLong(Organization205Query.RAW_CONTACT_ID);
26565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String company = cursor.getString(Organization205Query.COMPANY);
26575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String phoneticName = cursor.getString(Organization205Query.PHONETIC_NAME);
26585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                int phoneticNameStyle = splitter.guessPhoneticNameStyle(phoneticName);
26605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.bindLong(1, phoneticNameStyle);
26625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.bindLong(2, dataId);
26635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.execute();
26645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String sortKey = null;
26665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                if (phoneticName == null && company != null) {
26675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    int nameStyle = splitter.guessFullNameStyle(company);
26685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    nameStyle = splitter.getAdjustedFullNameStyle(nameStyle);
2669ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                    if (nameStyle == FullNameStyle.CHINESE ||
2670ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                            nameStyle == FullNameStyle.CJK ) {
2671ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                        sortKey = ContactLocaleUtils.getIntance()
2672ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                                .getSortKey(company, nameStyle);
26735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    }
26745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                }
26755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                if (sortKey == null) {
26775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    sortKey = company;
26785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                }
26795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                updateRawContact205(rawContactUpdate, rawContactId, company,
26815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        company, phoneticNameStyle, phoneticName, sortKey, sortKey);
26825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
26835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } finally {
26845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            cursor.close();
26855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
26865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
26875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
26885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void updateRawContact205(SQLiteStatement rawContactUpdate, long rawContactId,
26895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String displayName, String displayNameAlternative, int phoneticNameStyle,
26905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String phoneticName, String sortKeyPrimary, String sortKeyAlternative) {
26915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 1, displayName);
26925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 2, displayNameAlternative);
26935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 3, phoneticName);
26945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.bindLong(4, phoneticNameStyle);
26955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 5, sortKeyPrimary);
26965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 6, sortKeyAlternative);
26975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.bindLong(7, rawContactId);
26985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.execute();
26995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
27005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
2701f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov    private void upgrateToVersion206(SQLiteDatabase db) {
2702f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
2703f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                + " ADD " + RawContacts.NAME_VERIFIED + " INTEGER NOT NULL DEFAULT 0;");
2704f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov    }
2705f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov
270631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    /**
270731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     * Fix for the bug where name lookup records for organizations would get removed by
270831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     * unrelated updates of the data rows.
270931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     */
2710b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeToVersion300(SQLiteDatabase db) {
2711197411a6cc3f81b94a34ca207f267d43d8548f04Dmitri Plotnikov        // No longer needed
271231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    }
271331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
2714b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private static final class Upgrade303Query {
2715b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
2716b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2717b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String SELECTION =
2718b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=?" +
2719b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    " AND " + Data._ID + " NOT IN " +
2720b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    "(SELECT " + NameLookupColumns.DATA_ID + " FROM " + Tables.NAME_LOOKUP + ")" +
2721b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    " AND " + Data.DATA1 + " NOT NULL";
2722b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2723b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String COLUMNS[] = {
2724b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data._ID,
2725b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data.RAW_CONTACT_ID,
2726b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data.DATA1,
2727b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        };
2728b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2729b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int ID = 0;
2730b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
2731b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int DATA1 = 2;
2732b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2733b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2734b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    /**
2735b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * The {@link ContactsProvider2#update} method was deleting name lookup for new
2736b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * emails during the sync.  We need to restore the lost name lookup rows.
2737b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     */
2738b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeEmailToVersion303(SQLiteDatabase db) {
2739b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Email.CONTENT_ITEM_TYPE);
2740b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeTypeId == -1) {
2741b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return;
2742b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2743b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2744b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        ContentValues values = new ContentValues();
2745b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2746b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        // Find all data rows with the mime type "email" that are missing name lookup
2747b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Cursor cursor = db.query(Upgrade303Query.TABLE, Upgrade303Query.COLUMNS,
2748b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Upgrade303Query.SELECTION, new String[] {String.valueOf(mimeTypeId)},
2749b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                null, null, null);
2750b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2751b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            while (cursor.moveToNext()) {
2752b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long dataId = cursor.getLong(Upgrade303Query.ID);
2753b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long rawContactId = cursor.getLong(Upgrade303Query.RAW_CONTACT_ID);
2754b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                String value = cursor.getString(Upgrade303Query.DATA1);
2755b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                value = extractHandleFromEmailAddress(value);
2756b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2757b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                if (value != null) {
2758b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.DATA_ID, dataId);
2759b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
2760b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.NAME_TYPE, NameLookupType.EMAIL_BASED_NICKNAME);
2761b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME, NameNormalizer.normalize(value));
2762b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
2763b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                }
2764b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            }
2765b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } finally {
2766b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            cursor.close();
2767b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2768b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2769b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2770b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    /**
2771b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * The {@link ContactsProvider2#update} method was deleting name lookup for new
2772b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * nicknames during the sync.  We need to restore the lost name lookup rows.
2773b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     */
2774b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeNicknameToVersion303(SQLiteDatabase db) {
2775b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Nickname.CONTENT_ITEM_TYPE);
2776b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeTypeId == -1) {
2777b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return;
2778b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2779b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2780b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        ContentValues values = new ContentValues();
2781b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2782b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        // Find all data rows with the mime type "nickname" that are missing name lookup
2783b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Cursor cursor = db.query(Upgrade303Query.TABLE, Upgrade303Query.COLUMNS,
2784b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Upgrade303Query.SELECTION, new String[] {String.valueOf(mimeTypeId)},
2785b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                null, null, null);
2786b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2787b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            while (cursor.moveToNext()) {
2788b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long dataId = cursor.getLong(Upgrade303Query.ID);
2789b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long rawContactId = cursor.getLong(Upgrade303Query.RAW_CONTACT_ID);
2790b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                String value = cursor.getString(Upgrade303Query.DATA1);
2791b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2792b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.DATA_ID, dataId);
2793b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
2794b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.NAME_TYPE, NameLookupType.NICKNAME);
2795b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.NORMALIZED_NAME, NameNormalizer.normalize(value));
2796b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                db.insert(Tables.NAME_LOOKUP, null, values);
2797b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            }
2798b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } finally {
2799b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            cursor.close();
2800b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2801b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2802b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
280351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void upgradeToVersion304(SQLiteDatabase db) {
280451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        // Mimetype table requires an index on mime type
280551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS mime_type ON " + Tables.MIMETYPES + " (" +
280651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                MimetypesColumns.MIMETYPE +
280751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        ");");
280851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
280951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
281060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann    private void upgradeToVersion306(SQLiteDatabase db) {
281160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        // Fix invalid lookup that was used for Exchange contacts (it was not escaped)
281260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        // It happened when a new contact was created AND synchronized
281360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final StringBuilder lookupKeyBuilder = new StringBuilder();
281460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final SQLiteStatement updateStatement = db.compileStatement(
281560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "UPDATE contacts " +
281660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "SET lookup=? " +
281760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "WHERE _id=?");
281860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final Cursor contactIdCursor = db.rawQuery(
281960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "SELECT DISTINCT contact_id " +
282060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "FROM raw_contacts " +
282160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "WHERE deleted=0 AND account_type='com.android.exchange'",
282260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                null);
282360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        try {
282460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            while (contactIdCursor.moveToNext()) {
282560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                final long contactId = contactIdCursor.getLong(0);
282660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                lookupKeyBuilder.setLength(0);
282760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                final Cursor c = db.rawQuery(
282860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "SELECT account_type, account_name, _id, sourceid, display_name " +
282960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "FROM raw_contacts " +
283060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "WHERE contact_id=? " +
283160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "ORDER BY _id",
283260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        new String[] { String.valueOf(contactId) });
283360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                try {
283460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    while (c.moveToNext()) {
283560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        ContactLookupKey.appendToLookupKey(lookupKeyBuilder,
283660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(0),
283760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(1),
283860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getLong(2),
283960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(3),
284060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(4));
284160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    }
284260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                } finally {
284360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    c.close();
284460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                }
284560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
284660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                if (lookupKeyBuilder.length() == 0) {
284760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    updateStatement.bindNull(1);
284860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                } else {
284960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    updateStatement.bindString(1, Uri.encode(lookupKeyBuilder.toString()));
285060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                }
285160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                updateStatement.bindLong(2, contactId);
285260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
285360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                updateStatement.execute();
285460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            }
285560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        } finally {
285660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            updateStatement.close();
285760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            contactIdCursor.close();
285860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        }
285960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann    }
286060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
2861b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    private void upgradeToVersion307(SQLiteDatabase db) {
2862b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        db.execSQL("CREATE TABLE properties (" +
2863b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                "property_key TEXT PRIMARY_KEY, " +
2864b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                "property_value TEXT" +
2865b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ");");
2866b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
2867b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
2868743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov    private void upgradeToVersion308(SQLiteDatabase db) {
28694394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE accounts (" +
28704394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "account_name TEXT, " +
28714394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "account_type TEXT " +
28724394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
2873743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
28744394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO accounts " +
28754394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "SELECT DISTINCT account_name, account_type FROM raw_contacts");
2876743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov    }
2877743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
2878f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov    private void upgradeToVersion400(SQLiteDatabase db) {
2879dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        db.execSQL("ALTER TABLE " + Tables.GROUPS
2880dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + " ADD " + Groups.FAVORITES + " INTEGER NOT NULL DEFAULT 0;");
2881dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        db.execSQL("ALTER TABLE " + Tables.GROUPS
2882dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + " ADD " + Groups.AUTO_ADD + " INTEGER NOT NULL DEFAULT 0;");
2883dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana    }
2884dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana
28857da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov    private void upgradeToVersion353(SQLiteDatabase db) {
28867da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        db.execSQL("DELETE FROM contacts " +
28877da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov                "WHERE NOT EXISTS (SELECT 1 FROM raw_contacts WHERE contact_id=contacts._id)");
28887da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov    }
28897da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
289051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void rebuildNameLookup(SQLiteDatabase db) {
289151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
289251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        insertNameLookup(db);
289351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        createContactsIndexes(db);
289451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
289551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
289604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
289751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     * Regenerates all locale-sensitive data: nickname_lookup, name_lookup and sort keys.
289804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
289951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    public void setLocale(ContactsProvider2 provider, Locale locale) {
290051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        Log.i(TAG, "Switching to locale " + locale);
290104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
2902c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamilton        long start = SystemClock.uptimeMillis();
290351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
290451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.setLocale(locale);
290551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.beginTransaction();
290651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
290751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX raw_contact_sort_key1_index");
290851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX raw_contact_sort_key2_index");
290951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
291051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
291151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            loadNicknameLookupTable(db);
291251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertNameLookup(db);
291351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            rebuildSortKeys(db, provider);
291451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            createContactsIndexes(db);
291551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.setTransactionSuccessful();
291651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
291751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.endTransaction();
291851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
291951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
2920c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamilton        Log.i(TAG, "Locale change completed in " + (SystemClock.uptimeMillis() - start) + "ms");
292151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
292251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
292351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    /**
292451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     * Regenerates sort keys for all contacts.
292551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     */
292651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void rebuildSortKeys(SQLiteDatabase db, ContactsProvider2 provider) {
292751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        Cursor cursor = db.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID},
292851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                null, null, null, null, null);
292951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
293051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            while (cursor.moveToNext()) {
293151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                long rawContactId = cursor.getLong(0);
29328ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                updateRawContactDisplayName(db, rawContactId);
293351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            }
293451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
293551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            cursor.close();
293651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
293751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
293851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
293951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void insertNameLookup(SQLiteDatabase db) {
294004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NAME_LOOKUP);
294104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
294204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        SQLiteStatement nameLookupInsert = db.compileStatement(
294304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                "INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "("
294404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.RAW_CONTACT_ID + ","
294504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.DATA_ID + ","
294604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.NAME_TYPE + ","
294704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.NORMALIZED_NAME +
294804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                ") VALUES (?,?,?,?)");
294904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
295051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
295151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertStructuredNameLookup(db, nameLookupInsert);
295251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertEmailLookup(db, nameLookupInsert);
295351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertNicknameLookup(db, nameLookupInsert);
295451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
295551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            nameLookupInsert.close();
295651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
295704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
295804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
295904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class StructuredNameQuery {
296004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
296104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
296204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
296304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
296404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
296504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
296604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName._ID,
296704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName.RAW_CONTACT_ID,
296804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName.DISPLAY_NAME,
296904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
297004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
297104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
297204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
297304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int DISPLAY_NAME = 2;
297404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
297504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
297604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private class StructuredNameLookupBuilder extends NameLookupBuilder {
297704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
297804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        private final SQLiteStatement mNameLookupInsert;
297904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        private final CommonNicknameCache mCommonNicknameCache;
298004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
298104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public StructuredNameLookupBuilder(NameSplitter splitter,
298204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                CommonNicknameCache commonNicknameCache, SQLiteStatement nameLookupInsert) {
298304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            super(splitter);
298404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            this.mCommonNicknameCache = commonNicknameCache;
298504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            this.mNameLookupInsert = nameLookupInsert;
298604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
298704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
298804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        @Override
298904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        protected void insertNameLookup(long rawContactId, long dataId, int lookupType,
299004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String name) {
299104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            if (!TextUtils.isEmpty(name)) {
299204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                ContactsDatabaseHelper.this.insertNormalizedNameLookup(mNameLookupInsert,
299304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        rawContactId, dataId, lookupType, name);
299404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
299504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
299604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
299704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        @Override
299804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        protected String[] getCommonNicknameClusters(String normalizedName) {
299904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return mCommonNicknameCache.getCommonNicknameClusters(normalizedName);
300004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
300104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
300204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
300304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
300404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all structured names in the database.
300504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
300604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertStructuredNameLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
3007d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov        NameSplitter nameSplitter = createNameSplitter();
3008d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov        NameLookupBuilder nameLookupBuilder = new StructuredNameLookupBuilder(nameSplitter,
300904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                new CommonNicknameCache(db), nameLookupInsert);
301004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, StructuredName.CONTENT_ITEM_TYPE);
301104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(StructuredNameQuery.TABLE, StructuredNameQuery.COLUMNS,
301204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredNameQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
301304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
301404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
301504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
301604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(StructuredNameQuery.ID);
301704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(StructuredNameQuery.RAW_CONTACT_ID);
301804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String name = cursor.getString(StructuredNameQuery.DISPLAY_NAME);
3019d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov                int fullNameStyle = nameSplitter.guessFullNameStyle(name);
302051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                fullNameStyle = nameSplitter.getAdjustedFullNameStyle(fullNameStyle);
3021d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov                nameLookupBuilder.insertNameLookup(rawContactId, dataId, name, fullNameStyle);
302204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
302304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
302404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
302504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
302604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
302704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
302804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class OrganizationQuery {
302904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
303004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
303104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
303204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
303304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
303404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
303504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization._ID,
303604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.RAW_CONTACT_ID,
303704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.COMPANY,
303804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.TITLE,
303904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
304004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
304104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
304204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
304304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int COMPANY = 2;
304404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int TITLE = 3;
304504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
304604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
304704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class EmailQuery {
304804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
304904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
305004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
305104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
305204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
305304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
305404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email._ID,
305504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email.RAW_CONTACT_ID,
305604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email.ADDRESS,
305704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
305804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
305904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
306004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
306104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ADDRESS = 2;
306204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
306304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
306404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
306504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all email addresses in the database.
306604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
306704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertEmailLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
306804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Email.CONTENT_ITEM_TYPE);
306904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(EmailQuery.TABLE, EmailQuery.COLUMNS,
307004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                EmailQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
307104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
307204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
307304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
307404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(EmailQuery.ID);
307504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(EmailQuery.RAW_CONTACT_ID);
307604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String address = cursor.getString(EmailQuery.ADDRESS);
307704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                address = extractHandleFromEmailAddress(address);
307804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
307904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.EMAIL_BASED_NICKNAME, address);
308004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
308104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
308204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
308304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
308404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
308504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
308604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class NicknameQuery {
308704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
308804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
308904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
309004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
309104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
309204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
309304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname._ID,
309404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname.RAW_CONTACT_ID,
309504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname.NAME,
309604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
309704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
309804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
309904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
310004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int NAME = 2;
310104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
310204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
310304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
310404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all nicknames in the database.
310504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
310604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertNicknameLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
310704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Nickname.CONTENT_ITEM_TYPE);
310804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(NicknameQuery.TABLE, NicknameQuery.COLUMNS,
310904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                NicknameQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
311004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
311104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
311204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
311304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(NicknameQuery.ID);
311404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(NicknameQuery.RAW_CONTACT_ID);
311504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String nickname = cursor.getString(NicknameQuery.NAME);
311604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
311704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.NICKNAME, nickname);
311804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
311904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
312004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
312104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
312204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
312304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
312404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
312504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts a record in the {@link Tables#NAME_LOOKUP} table.
312604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
312704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    public void insertNameLookup(SQLiteStatement stmt, long rawContactId, long dataId,
312804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            int lookupType, String name) {
312904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (TextUtils.isEmpty(name)) {
313004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return;
313104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
313204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
313304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        String normalized = NameNormalizer.normalize(name);
313404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (TextUtils.isEmpty(normalized)) {
313504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return;
313604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
313704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
313804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        insertNormalizedNameLookup(stmt, rawContactId, dataId, lookupType, normalized);
313904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
314004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
314104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertNormalizedNameLookup(SQLiteStatement stmt, long rawContactId, long dataId,
314204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            int lookupType, String normalizedName) {
314304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(1, rawContactId);
314404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(2, dataId);
314504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(3, lookupType);
314604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindString(4, normalizedName);
314704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.executeInsert();
314804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
314904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
31504394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    /**
31514394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov     * Changing the VISIBLE bit from a field on both RawContacts and Contacts to a separate table.
31524394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov     */
31534394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    private void upgradeToVersion401(SQLiteDatabase db) {
31544394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.VISIBLE_CONTACTS + " (" +
31554394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
31564394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
31574394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.VISIBLE_CONTACTS +
31584394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " SELECT " + Contacts._ID +
31594394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " FROM " + Tables.CONTACTS +
31604394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " WHERE " + Contacts.IN_VISIBLE_GROUP + "!=0");
31614394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("DROP INDEX contacts_visible_index");
31624394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    }
31634394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
3164d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    /**
3165d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov     * Introducing a new table: directories.
3166d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov     */
3167d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    private void upgradeToVersion402(SQLiteDatabase db) {
3168d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        createDirectoriesTable(db);
3169d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    }
3170d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
317197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    private void upgradeToVersion403(SQLiteDatabase db) {
317297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
317397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        createDirectoriesTable(db);
317497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
317597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("ALTER TABLE raw_contacts"
317697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + " ADD raw_contact_is_read_only INTEGER NOT NULL DEFAULT 0;");
317797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
317897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("ALTER TABLE data"
317997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + " ADD is_read_only INTEGER NOT NULL DEFAULT 0;");
318097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    }
318197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
3182892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    private void upgradeToVersion405(SQLiteDatabase db) {
3183892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS phone_lookup;");
3184892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        // Private phone numbers table used for lookup
3185892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" +
3186892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID
3187892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " INTEGER REFERENCES data(_id) NOT NULL," +
3188892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID
3189892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
3190892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL," +
3191892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL" +
3192892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
3193892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
3194892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" +
3195892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + "," +
3196892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
3197892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
3198892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
3199892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
3200892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
3201892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
3202892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
3203892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
3204892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
3205892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
3206892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Phone.CONTENT_ITEM_TYPE);
3207892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (mimeTypeId == -1) {
3208892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            return;
3209892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
3210892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
3211892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        Cursor cursor = db.rawQuery(
3212892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    "SELECT _id, " + Phone.RAW_CONTACT_ID + ", " + Phone.NUMBER +
3213892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    " FROM " + Tables.DATA +
3214892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId
3215892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                            + " AND " + Phone.NUMBER + " NOT NULL", null);
3216892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
3217892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ContentValues phoneValues = new ContentValues();
3218892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        try {
3219892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            while (cursor.moveToNext()) {
3220892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                long dataID = cursor.getLong(0);
3221892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                long rawContactID = cursor.getLong(1);
3222892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String number = cursor.getString(2);
3223892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String normalizedNumber = PhoneNumberUtils.normalizeNumber(number);
3224892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                if (!TextUtils.isEmpty(normalizedNumber)) {
3225892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.clear();
3226892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactID);
3227892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.DATA_ID, dataID);
3228892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber);
3229892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.MIN_MATCH,
3230892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                            PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber));
3231892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    db.insert(Tables.PHONE_LOOKUP, null, phoneValues);
3232892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                }
3233892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3234892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        } finally {
3235892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            cursor.close();
3236892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
3237892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    }
3238892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
32392530512f639c4979fd7371c7dd25dd67e8118124Bai Tao    private void upgradeToVersion406(SQLiteDatabase db) {
32402530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        db.execSQL("ALTER TABLE calls ADD countryiso TEXT;");
32412530512f639c4979fd7371c7dd25dd67e8118124Bai Tao    }
32422530512f639c4979fd7371c7dd25dd67e8118124Bai Tao
3243d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    private void upgradeToVersion409(SQLiteDatabase db) {
3244d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
3245d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        createDirectoriesTable(db);
3246d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    }
3247d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov
3248385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    /**
3249d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov     * Adding DEFAULT_DIRECTORY table.
32503e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa     * DEFAULT_DIRECTORY should contain every contact which should be shown to users in default.
32513e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa     * - if a contact doesn't belong to any account (local contact), it should be in
32523e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa     *   default_directory
32533e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa     * - if a contact belongs to an account that doesn't have a "default" group, it should be in
32543e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa     *   default_directory
32553e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa     * - if a contact belongs to an account that has a "default" group (like Google directory,
32563e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa     *   which has "My contacts" group as default), it should be in default_directory.
32573e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa     *
32583e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa     * This logic assumes that accounts with the "default" group should have at least one
32593e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa     * group with AUTO_ADD (implying it is the default group) flag in the groups table.
3260385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     */
3261d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    private void upgradeToVersion411(SQLiteDatabase db) {
3262d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS " + Tables.DEFAULT_DIRECTORY);
32633e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa        db.execSQL("CREATE TABLE default_directory (_id INTEGER PRIMARY KEY);");
3264385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3265385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // Process contacts without an account
32663e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa        db.execSQL("INSERT OR IGNORE INTO default_directory " +
32673e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                " SELECT contact_id " +
32683e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                " FROM raw_contacts " +
32693e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                " WHERE raw_contacts.account_name IS NULL " +
32703e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "   AND raw_contacts.account_type IS NULL ");
32713e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa
32723e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa        // Process accounts that don't have a default group (e.g. Exchange).
32733e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa        db.execSQL("INSERT OR IGNORE INTO default_directory " +
32743e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                " SELECT contact_id " +
32753e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                " FROM raw_contacts " +
3276385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE NOT EXISTS" +
32773e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                " (SELECT _id " +
32783e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "  FROM groups " +
32793e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "  WHERE raw_contacts.account_name = groups.account_name" +
32803e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "    AND raw_contacts.account_type = groups.account_type" +
32813e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "    AND groups.auto_add != 0)");
3282385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
32833e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa        final long mimetype = lookupMimeTypeId(db, GroupMembership.CONTENT_ITEM_TYPE);
3284385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3285d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        // Process accounts that do have a default group (e.g. Google)
32863e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa        db.execSQL("INSERT OR IGNORE INTO default_directory " +
32873e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                " SELECT contact_id " +
32883e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                " FROM raw_contacts " +
32893e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                " JOIN data " +
32903e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "   ON (raw_contacts._id=raw_contact_id)" +
32913e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                " WHERE mimetype_id=" + mimetype +
3292d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                " AND EXISTS" +
32933e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                " (SELECT _id" +
32943e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "  FROM groups" +
32953e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "  WHERE raw_contacts.account_name = groups.account_name" +
32963e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "    AND raw_contacts.account_type = groups.account_type" +
32973e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa                "    AND groups.auto_add != 0)");
32983d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
3299385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3300e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    private void upgradeToVersion413(SQLiteDatabase db) {
33013ea7932a47027c8629d3a301e1a16e7d2c8a298dDmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
33023ea7932a47027c8629d3a301e1a16e7d2c8a298dDmitri Plotnikov        createDirectoriesTable(db);
3303e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    }
3304e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov
3305c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov    private void upgradeToVersion415(SQLiteDatabase db) {
3306c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        db.execSQL(
3307c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "ALTER TABLE " + Tables.GROUPS +
3308c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                " ADD " + Groups.GROUP_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0");
3309c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        db.execSQL(
3310c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "UPDATE " + Tables.GROUPS +
3311c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "   SET " + Groups.GROUP_IS_READ_ONLY + "=1" +
3312c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                " WHERE " + Groups.SYSTEM_ID + " NOT NULL");
3313c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov    }
3314c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov
3315d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov    private void upgradeToVersion416(SQLiteDatabase db) {
3316d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_data_id_min_match_index ON " + Tables.PHONE_LOOKUP +
3317d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov                " (" + PhoneLookupColumns.DATA_ID + ", " + PhoneLookupColumns.MIN_MATCH + ");");
3318d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov    }
3319d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov
3320197411a6cc3f81b94a34ca207f267d43d8548f04Dmitri Plotnikov    private void upgradeToVersion501(SQLiteDatabase db) {
3321197411a6cc3f81b94a34ca207f267d43d8548f04Dmitri Plotnikov        // Remove organization rows from the name lookup, we now use search index for that
3322197411a6cc3f81b94a34ca207f267d43d8548f04Dmitri Plotnikov        db.execSQL("DELETE FROM name_lookup WHERE name_type=5");
3323f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov    }
3324f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov
332592ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov    private void upgradeToVersion502(SQLiteDatabase db) {
332692ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov        // Remove Chinese and Korean name lookup - this data is now in the search index
332792ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov        db.execSQL("DELETE FROM name_lookup WHERE name_type IN (6, 7)");
332892ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov    }
332992ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov
333055e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov    private void upgradeToVersion504(SQLiteDatabase db) {
333155e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        populateMimeTypeCache(db);
333255e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov
333355e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        // Find all names with prefixes and recreate display name
333455e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        Cursor cursor = db.rawQuery(
333555e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov                "SELECT " + StructuredName.RAW_CONTACT_ID +
333655e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov                " FROM " + Tables.DATA +
333755e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov                " WHERE " + DataColumns.MIMETYPE_ID + "=?"
333855e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov                        + " AND " + StructuredName.PREFIX + " NOT NULL",
333955e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov                new String[]{ String.valueOf(mMimeTypeIdStructuredName) });
334055e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov
334155e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        try {
334255e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            while(cursor.moveToNext()) {
334355e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov                long rawContactId = cursor.getLong(0);
334455e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov                updateRawContactDisplayName(db, rawContactId);
334555e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            }
334655e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov
334755e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        } finally {
334855e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            cursor.close();
334955e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        }
335055e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov    }
335155e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov
335224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro    private void upgradeToVersion600(SQLiteDatabase db) {
33535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        // This change used to add the profile raw contact ID to the Accounts table.  That
33545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        // column is no longer needed (as of version 614) since the profile records are stored in
33555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        // a separate copy of the database for security reasons.  So this change is now a no-op.
335624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro    }
335724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro
335846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa    private void upgradeToVersion601(SQLiteDatabase db) {
335946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        db.execSQL("CREATE TABLE data_usage_stat(" +
336046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                "stat_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
336146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                "data_id INTEGER NOT NULL, " +
336246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                "usage_type INTEGER NOT NULL DEFAULT 0, " +
336346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                "times_used INTEGER NOT NULL DEFAULT 0, " +
336446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                "last_time_used INTERGER NOT NULL DEFAULT 0, " +
336546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                "FOREIGN KEY(data_id) REFERENCES data(_id));");
336646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa        db.execSQL("CREATE UNIQUE INDEX data_usage_stat_index ON " +
336746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa                "data_usage_stat (data_id, usage_type)");
336846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa    }
336946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa
337059f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee    private void upgradeToVersion602(SQLiteDatabase db) {
337159f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee        db.execSQL("ALTER TABLE calls ADD voicemail_uri TEXT;");
337259f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee        db.execSQL("ALTER TABLE calls ADD _data TEXT;");
337359f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee        db.execSQL("ALTER TABLE calls ADD has_content INTEGER;");
337459f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee        db.execSQL("ALTER TABLE calls ADD mime_type TEXT;");
337559f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee        db.execSQL("ALTER TABLE calls ADD source_data TEXT;");
337659f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee        db.execSQL("ALTER TABLE calls ADD source_package TEXT;");
337759f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee        db.execSQL("ALTER TABLE calls ADD state INTEGER;");
337859f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee    }
337959f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee
3380069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee    private void upgradeToVersion604(SQLiteDatabase db) {
3381069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee        db.execSQL("CREATE TABLE voicemail_status (" +
3382069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee                "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
3383069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee                "source_package TEXT UNIQUE NOT NULL," +
3384069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee                "settings_uri TEXT," +
3385069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee                "voicemail_access_uri TEXT," +
3386069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee                "configuration_state INTEGER," +
3387069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee                "data_channel_state INTEGER," +
3388069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee                "notification_channel_state INTEGER" +
3389069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee        ");");
3390069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee    }
3391069fdf5902415ebd6c92e5d889740e0d50cfec8dDebashish Chatterjee
33923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann    private void upgradeToVersion605(SQLiteDatabase db) {
33936802030a777c0c3ba1dc029c534cca4784260632Dave Santoro        // This version used to create the stream item and stream item photos tables, but a newer
33946802030a777c0c3ba1dc029c534cca4784260632Dave Santoro        // version of those tables is created in version 609 below.  So omitting the creation in
33956802030a777c0c3ba1dc029c534cca4784260632Dave Santoro        // this upgrade step to avoid a create->drop->create.
33963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann    }
33973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann
3398ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann    private void upgradeToVersion606(SQLiteDatabase db) {
3399ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("DROP VIEW IF EXISTS view_contacts_restricted;");
3400ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("DROP VIEW IF EXISTS view_data_restricted;");
3401ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("DROP VIEW IF EXISTS view_raw_contacts_restricted;");
3402ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("DROP VIEW IF EXISTS view_raw_entities_restricted;");
3403ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("DROP VIEW IF EXISTS view_entities_restricted;");
3404ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("DROP VIEW IF EXISTS view_data_usage_stat_restricted;");
3405ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        db.execSQL("DROP INDEX IF EXISTS contacts_restricted_index");
3406ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann
3407ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        // We should remove the restricted columns here as well, but unfortunately SQLite doesn't
3408ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann        // provide ALTER TABLE DROP COLUMN. As they have DEFAULT 0, we can keep but ignore them
3409ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann    }
3410ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann
34111cdfc9dacc136e99d3c0bc5b4212bc3c973be337Daniel Lehmann    private void upgradeToVersion607(SQLiteDatabase db) {
34120bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // We added "action" and "action_uri" to groups here, but realized this was not a smart
34130bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // move. This upgrade step has been removed (all dogfood phones that executed this step
34140bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // will have those columns, but that shouldn't hurt. Unfortunately, SQLite makes it hard
34150bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // to remove columns)
34161cdfc9dacc136e99d3c0bc5b4212bc3c973be337Daniel Lehmann    }
34171cdfc9dacc136e99d3c0bc5b4212bc3c973be337Daniel Lehmann
3418f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro    private void upgradeToVersion608(SQLiteDatabase db) {
3419f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro        db.execSQL("ALTER TABLE contacts ADD photo_file_id INTEGER REFERENCES photo_files(_id);");
3420f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro
3421f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro        db.execSQL("CREATE TABLE photo_files(" +
3422f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                "_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
3423f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                "height INTEGER NOT NULL, " +
3424f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                "width INTEGER NOT NULL, " +
3425f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro                "filesize INTEGER NOT NULL);");
3426f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro    }
3427f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro
34286802030a777c0c3ba1dc029c534cca4784260632Dave Santoro    private void upgradeToVersion609(SQLiteDatabase db) {
34290bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // This version used to create the stream item and stream item photos tables, but a newer
34300bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // version of those tables is created in version 613 below.  So omitting the creation in
34310bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // this upgrade step to avoid a create->drop->create.
34326802030a777c0c3ba1dc029c534cca4784260632Dave Santoro    }
34336802030a777c0c3ba1dc029c534cca4784260632Dave Santoro
3434b2197b235e3d96e7f70c24d548b7dac52dab88d8Flavio Lerda    private void upgradeToVersion610(SQLiteDatabase db) {
3435b2197b235e3d96e7f70c24d548b7dac52dab88d8Flavio Lerda        db.execSQL("ALTER TABLE calls ADD is_read INTEGER;");
3436b2197b235e3d96e7f70c24d548b7dac52dab88d8Flavio Lerda    }
3437b2197b235e3d96e7f70c24d548b7dac52dab88d8Flavio Lerda
343843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro    private void upgradeToVersion611(SQLiteDatabase db) {
343943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        db.execSQL("ALTER TABLE raw_contacts ADD data_set TEXT DEFAULT NULL;");
344043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        db.execSQL("ALTER TABLE groups ADD data_set TEXT DEFAULT NULL;");
344143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        db.execSQL("ALTER TABLE accounts ADD data_set TEXT DEFAULT NULL;");
344243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro
344343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        db.execSQL("CREATE INDEX raw_contacts_source_id_data_set_index ON raw_contacts " +
344443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                "(sourceid, account_type, account_name, data_set);");
344543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro
344643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        db.execSQL("CREATE INDEX groups_source_id_data_set_index ON groups " +
344743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                "(sourceid, account_type, account_name, data_set);");
344843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro    }
344943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro
3450aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda    private void upgradeToVersion612(SQLiteDatabase db) {
3451aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda        db.execSQL("ALTER TABLE calls ADD geocoded_location TEXT DEFAULT NULL;");
3452aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda        // Old calls will not have a geocoded location; new calls will get it when inserted.
3453aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda    }
3454aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda
34550bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann    private void upgradeToVersion613(SQLiteDatabase db) {
34560bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // The stream item and stream item photos APIs were not in-use by anyone in the time
34570bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // between their initial creation (in v609) and this update.  So we're just dropping
34580bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // and re-creating them to get appropriate columns.  The delta is as follows:
34590bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // - In stream_items, package_id was replaced by res_package.
34600bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // - In stream_item_photos, picture was replaced by photo_file_id.
34610bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // - Instead of resource ids for icon and label, we use resource name strings now
34620bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // - Added sync columns
34630bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // - Removed action and action_uri
34640bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        // - Text and comments are now nullable
34650bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann
34660bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        db.execSQL("DROP TABLE IF EXISTS stream_items");
34670bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        db.execSQL("DROP TABLE IF EXISTS stream_item_photos");
34680bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann
34690bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        db.execSQL("CREATE TABLE stream_items(" +
34700bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
34710bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "raw_contact_id INTEGER NOT NULL, " +
34720bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "res_package TEXT, " +
34730bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "icon TEXT, " +
34740bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "label TEXT, " +
34750bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "text TEXT, " +
34760bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "timestamp INTEGER NOT NULL, " +
34770bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "comments TEXT, " +
34780bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "stream_item_sync1 TEXT, " +
34790bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "stream_item_sync2 TEXT, " +
34800bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "stream_item_sync3 TEXT, " +
34810bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "stream_item_sync4 TEXT, " +
34820bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "FOREIGN KEY(raw_contact_id) REFERENCES raw_contacts(_id));");
34830bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann
34840bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann        db.execSQL("CREATE TABLE stream_item_photos(" +
34850bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
34860bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "stream_item_id INTEGER NOT NULL, " +
34870bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "sort_index INTEGER, " +
34880bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "photo_file_id INTEGER NOT NULL, " +
34890bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "stream_item_photo_sync1 TEXT, " +
34900bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "stream_item_photo_sync2 TEXT, " +
34910bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "stream_item_photo_sync3 TEXT, " +
34920bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "stream_item_photo_sync4 TEXT, " +
34930bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann                "FOREIGN KEY(stream_item_id) REFERENCES stream_items(_id));");
34940bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann    }
34950bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann
34967a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda    private void upgradeToVersion615(SQLiteDatabase db) {
34977a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda        // Old calls will not have up to date values for these columns, they will be filled in
34987a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda        // as needed.
34997a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda        db.execSQL("ALTER TABLE calls ADD lookup_uri TEXT DEFAULT NULL;");
35007a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda        db.execSQL("ALTER TABLE calls ADD matched_number TEXT DEFAULT NULL;");
35017a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda        db.execSQL("ALTER TABLE calls ADD normalized_number TEXT DEFAULT NULL;");
35027a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda        db.execSQL("ALTER TABLE calls ADD photo_id INTEGER NOT NULL DEFAULT 0;");
35037a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda    }
35047a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda
3505f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro    private void upgradeToVersion618(SQLiteDatabase db) {
3506f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro        // The Settings table needs a data_set column which technically should be part of the
3507f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro        // primary key but can't be because it may be null.  Since SQLite doesn't support nuking
3508f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro        // the primary key, we'll drop the old table, re-create it, and copy the settings back in.
3509f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro        db.execSQL("CREATE TEMPORARY TABLE settings_backup(" +
3510f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                "account_name STRING NOT NULL," +
3511f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                "account_type STRING NOT NULL," +
3512f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                "ungrouped_visible INTEGER NOT NULL DEFAULT 0," +
3513f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                "should_sync INTEGER NOT NULL DEFAULT 1" +
3514f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro        ");");
3515f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro        db.execSQL("INSERT INTO settings_backup " +
3516f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                "SELECT account_name, account_type, ungrouped_visible, should_sync" +
3517f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                " FROM settings");
3518f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro        db.execSQL("DROP TABLE settings");
3519f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro        db.execSQL("CREATE TABLE settings (" +
3520f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                "account_name STRING NOT NULL," +
3521f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                "account_type STRING NOT NULL," +
3522f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                "data_set STRING," +
3523f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                "ungrouped_visible INTEGER NOT NULL DEFAULT 0," +
3524f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                "should_sync INTEGER NOT NULL DEFAULT 1" +
3525f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro        ");");
3526f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro        db.execSQL("INSERT INTO settings " +
3527f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                "SELECT account_name, account_type, NULL, ungrouped_visible, should_sync " +
3528f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro                "FROM settings_backup");
3529f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro        db.execSQL("DROP TABLE settings_backup");
3530f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro    }
3531f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro
353213ed28505ed1af4f0b4a6297c4c6840d91f10c8cFlavio Lerda    private void upgradeToVersion622(SQLiteDatabase db) {
353313ed28505ed1af4f0b4a6297c4c6840d91f10c8cFlavio Lerda        db.execSQL("ALTER TABLE calls ADD formatted_number TEXT DEFAULT NULL;");
353413ed28505ed1af4f0b4a6297c4c6840d91f10c8cFlavio Lerda    }
353513ed28505ed1af4f0b4a6297c4c6840d91f10c8cFlavio Lerda
3536b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    public String extractHandleFromEmailAddress(String email) {
3537b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email);
3538b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (tokens.length == 0) {
3539b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return null;
3540b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
3541b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
3542b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        String address = tokens[0].getAddress();
3543b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        int at = address.indexOf('@');
3544b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (at != -1) {
3545b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return address.substring(0, at);
3546b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
3547b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        return null;
3548b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
3549b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
355008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov    public String extractAddressFromEmailAddress(String email) {
355108768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email);
355208768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        if (tokens.length == 0) {
355308768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            return null;
355408768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        }
355508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
355650a7c86b4b49870bd19d5270722be3f1fccaf226Dmitri Plotnikov        return tokens[0].getAddress().trim();
355708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov    }
355808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
35593e2aeb5c57d968d1dc98ba3f92f658eb7dd0cb7dDaisuke Miyakawa    private static long lookupMimeTypeId(SQLiteDatabase db, String mimeType) {
3560b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
3561b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return DatabaseUtils.longForQuery(db,
3562b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    "SELECT " + MimetypesColumns._ID +
3563b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    " FROM " + Tables.MIMETYPES +
3564b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    " WHERE " + MimetypesColumns.MIMETYPE
3565b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                            + "='" + mimeType + "'", null);
3566b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } catch (SQLiteDoneException e) {
3567b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            // No rows of this type in the database
3568b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return -1;
3569b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
3570b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
3571b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
35725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void bindString(SQLiteStatement stmt, int index, String value) {
35735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (value == null) {
35745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            stmt.bindNull(index);
35755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } else {
35765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            stmt.bindString(index, value);
35775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
35785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
35795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
358078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private void bindLong(SQLiteStatement stmt, int index, Number value) {
358178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (value == null) {
358278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            stmt.bindNull(index);
358378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        } else {
358478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            stmt.bindLong(index, value.longValue());
358578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
358678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
358778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
3588a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    /**
3589f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * Adds index stats into the SQLite database to force it to always use the lookup indexes.
3590f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     */
3591f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    private void updateSqliteStats(SQLiteDatabase db) {
3592f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
3593f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        // Specific stats strings are based on an actual large database after running ANALYZE
359472c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann        // Important here are relative sizes. Raw-Contacts is slightly bigger than Contacts
359572c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann        // Warning: Missing tables in here will make SQLite assume to contain 1000000 rows,
359672c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann        // which can lead to catastrophic query plans for small tables
3597f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        try {
359872c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            db.execSQL("DELETE FROM sqlite_stat1");
35998fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.CONTACTS,
360072c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "contacts_has_phone_index", "9000 500");
360172c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.CONTACTS,
360272c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "contacts_name_raw_contact_id_index", "9000 1");
36038fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
36048fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.RAW_CONTACTS,
36058fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "raw_contacts_source_id_index", "10000 1 1 1");
36068fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.RAW_CONTACTS,
36078fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "raw_contacts_contact_id_index", "10000 2");
360872c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.RAW_CONTACTS,
360972c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "raw_contact_sort_key2_index", "10000 2");
361072c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.RAW_CONTACTS,
361172c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "raw_contact_sort_key1_index", "10000 2");
361272c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.RAW_CONTACTS,
361372c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "raw_contacts_source_id_data_set_index", "10000 1 1 1 1");
36148fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
36158fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
361672c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "name_lookup_raw_contact_id_index", "35000 4");
36178fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
361872c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "name_lookup_index", "35000 2 2 2 1");
36198fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
362072c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "sqlite_autoindex_name_lookup_1", "35000 3 2 1");
36218fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
36228fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.PHONE_LOOKUP,
362372c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "phone_lookup_index", "3500 3 2 1");
362472c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.PHONE_LOOKUP,
362572c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "phone_lookup_min_match_index", "3500 3 2 2");
362636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            updateIndexStats(db, Tables.PHONE_LOOKUP,
362772c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "phone_lookup_data_id_min_match_index", "3500 2 2");
36288fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
36298fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.DATA,
36308fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "data_mimetype_data1_index", "60000 5000 2");
36318fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.DATA,
36328fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "data_raw_contact_id", "60000 10");
36338fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
36348fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.GROUPS,
363572c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "groups_source_id_index", "50 2 2 1");
363672c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.GROUPS,
363772c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "groups_source_id_data_set_index", "50 2 2 1 1");
36388fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
36398fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NICKNAME_LOOKUP,
364072c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "nickname_lookup_index", "500 2 1");
364172c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann
364272c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.CALLS,
364372c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "250");
364472c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann
364572c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.STATUS_UPDATES,
364672c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "100");
364772c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann
364872c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.STREAM_ITEMS,
364972c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "500");
365072c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.STREAM_ITEM_PHOTOS,
365172c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "50");
365272c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann
365372c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.ACTIVITIES,
365472c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "5");
365572c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann
365672c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.VOICEMAIL_STATUS,
365772c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "5");
365872c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann
365972c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.ACCOUNTS,
366072c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "3");
366172c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann
366272c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.VISIBLE_CONTACTS,
366372c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "2000");
366472c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann
366572c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.PHOTO_FILES,
366672c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "50");
366772c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann
366872c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.DEFAULT_DIRECTORY,
366972c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "1500");
367072c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann
367172c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.MIMETYPES,
367272c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "mime_type", "18 1");
367372c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann
367472c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.DATA_USAGE_STAT,
367572c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "data_usage_stat_index", "20 2 1");
367672c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann
367772c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            // Tiny tables
367872c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.AGGREGATION_EXCEPTIONS,
367972c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "10");
368072c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.SETTINGS,
368172c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "10");
368272c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.PACKAGES,
368372c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "0");
368472c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, Tables.DIRECTORIES,
368572c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "3");
368672c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, LegacyApiSupport.LegacyTables.SETTINGS,
368772c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "0");
368872c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, "android_metadata",
368972c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "1");
369072c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, "_sync_state",
369172c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "sqlite_autoindex__sync_state_1", "2 1 1");
369272c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, "_sync_state_metadata",
369372c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "1");
369472c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, "properties",
369572c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "sqlite_autoindex_properties_1", "4 1");
369672c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann
369772c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            // Search index
369872c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, "search_index_docsize",
369972c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "9000");
370072c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, "search_index_content",
370172c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "9000");
370272c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, "search_index_stat",
370372c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "1");
370472c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, "search_index_segments",
370572c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    null, "450");
370672c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            updateIndexStats(db, "search_index_segdir",
370772c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    "sqlite_autoindex_search_index_segdir_1", "9 5 1");
37088fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
3709f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        } catch (SQLException e) {
3710f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            Log.e(TAG, "Could not update index stats", e);
3711f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        }
3712f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
3713f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
3714f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    /**
3715f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * Stores statistics for a given index.
3716f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     *
3717f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * @param stats has the following structure: the first index is the expected size of
3718f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * the table.  The following integer(s) are the expected number of records selected with the
3719f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * index.  There should be one integer per indexed column.
3720f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     */
37215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void updateIndexStats(SQLiteDatabase db, String table, String index,
37225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String stats) {
372372c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann        if (index == null) {
372472c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            db.execSQL("DELETE FROM sqlite_stat1 WHERE tbl=? AND idx IS NULL",
372572c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    new String[] { table });
372672c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann        } else {
372772c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann            db.execSQL("DELETE FROM sqlite_stat1 WHERE tbl=? AND idx=?",
372872c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                    new String[] { table, index });
372972c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann        }
373072c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann        db.execSQL("INSERT INTO sqlite_stat1 (tbl,idx,stat) VALUES (?,?,?)",
373172c4b2612a06636343e2803c0c84fdfbd5ba2f63Daniel Lehmann                new String[] { table, index, stats });
3732f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
3733f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
3734f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    @Override
3735f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    public synchronized SQLiteDatabase getWritableDatabase() {
3736f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        SQLiteDatabase db = super.getWritableDatabase();
3737f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        if (mReopenDatabase) {
3738f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            mReopenDatabase = false;
3739f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            close();
3740f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            db = super.getWritableDatabase();
3741f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        }
3742f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        return db;
3743f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
3744f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
3745f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    /**
3746a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov     * Wipes all data except mime type and package lookup tables.
3747a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov     */
3748a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    public void wipeData() {
3749a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
37503d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov
375133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.ACCOUNTS + ";");
37525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " VALUES(NULL, NULL, NULL)");
375333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov
3754d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CONTACTS + ";");
37555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.RAW_CONTACTS + ";");
37563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann        db.execSQL("DELETE FROM " + Tables.STREAM_ITEMS + ";");
37573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann        db.execSQL("DELETE FROM " + Tables.STREAM_ITEM_PHOTOS + ";");
3758f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro        db.execSQL("DELETE FROM " + Tables.PHOTO_FILES + ";");
3759a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.DATA + ";");
3760a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.PHONE_LOOKUP + ";");
3761a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NAME_LOOKUP + ";");
3762ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("DELETE FROM " + Tables.GROUPS + ";");
3763b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.AGGREGATION_EXCEPTIONS + ";");
3764eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        db.execSQL("DELETE FROM " + Tables.SETTINGS + ";");
3765a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.ACTIVITIES + ";");
37663d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CALLS + ";");
376772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.DIRECTORIES + ";");
3768f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.SEARCH_INDEX + ";");
376972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov
3770b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        // Note: we are not removing reference data from Tables.NICKNAME_LOOKUP
3771a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
3772b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
377304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    public NameSplitter createNameSplitter() {
37748ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        mNameSplitter = new NameSplitter(
377504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_prefixes),
377604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_last_name_prefixes),
377704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_suffixes),
377804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_conjunctions),
377904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Locale.getDefault());
37808ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        return mNameSplitter;
378104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
378204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
3783b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3784619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey     * Return the {@link ApplicationInfo#uid} for the given package name.
3785619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey     */
3786619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    public static int getUidForPackageName(PackageManager pm, String packageName) {
3787619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        try {
3788619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            ApplicationInfo clientInfo = pm.getApplicationInfo(packageName, 0 /* no flags */);
3789619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            return clientInfo.uid;
3790619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        } catch (NameNotFoundException e) {
3791619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            throw new RuntimeException(e);
3792619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        }
3793619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
3794619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
3795619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    /**
3796b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Perform an internal string-to-integer lookup using the compiled
379711a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann     * {@link SQLiteStatement} provided. If a mapping isn't found in database, it will be
3798b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * created. All new, uncached answers are added to the cache automatically.
3799b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *
3800b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param query Compiled statement used to query for the mapping.
3801b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param insert Compiled statement used to insert a new mapping when no
3802b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *            existing one is found in cache or from query.
3803b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param value Value to find mapping for.
3804b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param cache In-memory cache of previous answers.
3805b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @return An unique integer mapping for the given value.
3806b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
380711a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann    private long lookupAndCacheId(SQLiteStatement query, SQLiteStatement insert,
3808b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String value, HashMap<String, Long> cache) {
380911a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        long id = -1;
381011a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        try {
381111a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            // Try searching database for mapping
381211a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            DatabaseUtils.bindObjectToProgram(query, 1, value);
381311a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            id = query.simpleQueryForLong();
381411a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        } catch (SQLiteDoneException e) {
381511a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            // Nothing found, so try inserting new mapping
381611a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            DatabaseUtils.bindObjectToProgram(insert, 1, value);
381711a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            id = insert.executeInsert();
381811a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        }
381911a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        if (id != -1) {
382011a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            // Cache and return the new answer
382111a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            cache.put(value, id);
382211a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            return id;
382311a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        } else {
382411a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            // Otherwise throw if no mapping found or created
382511a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            throw new IllegalStateException("Couldn't find or create internal "
382611a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann                    + "lookup table entry for value " + value);
3827b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3828b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3829b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3830b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3831ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Convert a package name into an integer, using {@link Tables#PACKAGES} for
3832b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
3833b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3834b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getPackageId(String packageName) {
383511a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        // Try an in-memory cache lookup
383611a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        if (mPackageCache.containsKey(packageName)) return mPackageCache.get(packageName);
383778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
383811a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        final SQLiteStatement packageQuery = getWritableDatabase().compileStatement(
383911a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann                "SELECT " + PackagesColumns._ID +
384011a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann                " FROM " + Tables.PACKAGES +
384111a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann                " WHERE " + PackagesColumns.PACKAGE + "=?");
384211a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann
384311a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        final SQLiteStatement packageInsert = getWritableDatabase().compileStatement(
384411a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann                "INSERT INTO " + Tables.PACKAGES + "("
384511a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann                        + PackagesColumns.PACKAGE +
384611a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann                ") VALUES (?)");
384711a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        try {
384811a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            return lookupAndCacheId(packageQuery, packageInsert, packageName, mPackageCache);
384911a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        } finally {
385011a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            packageQuery.close();
385111a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            packageInsert.close();
385278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3853b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3854b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3855b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3856ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Convert a mimetype into an integer, using {@link Tables#MIMETYPES} for
3857b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
3858b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3859b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getMimeTypeId(String mimetype) {
386011a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        // Try an in-memory cache lookup
386111a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        if (mMimetypeCache.containsKey(mimetype)) return mMimetypeCache.get(mimetype);
386211a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann
386311a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        return lookupMimeTypeId(mimetype, getWritableDatabase());
386411a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann    }
386511a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann
386611a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann    private long lookupMimeTypeId(String mimetype, SQLiteDatabase db) {
386711a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        final SQLiteStatement mimetypeQuery = db.compileStatement(
386811a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann                "SELECT " + MimetypesColumns._ID +
386911a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann                " FROM " + Tables.MIMETYPES +
387011a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann                " WHERE " + MimetypesColumns.MIMETYPE + "=?");
387111a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann
387211a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        final SQLiteStatement mimetypeInsert = db.compileStatement(
387311a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann                "INSERT INTO " + Tables.MIMETYPES + "("
387411a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann                        + MimetypesColumns.MIMETYPE +
387511a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann                ") VALUES (?)");
387611a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann
387711a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        try {
387811a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            return lookupAndCacheId(mimetypeQuery, mimetypeInsert, mimetype, mMimetypeCache);
387911a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        } finally {
388011a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            mimetypeQuery.close();
388111a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann            mimetypeInsert.close();
388211a83441a0f66440dcf1a560194dcc11979f0c2cDaniel Lehmann        }
3883b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3884b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
38852a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForStructuredName() {
38862a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdStructuredName;
38872a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
38882a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
38897cf50494501938f175d288077145acf49da8f171Daniel Lehmann    public long getMimeTypeIdForStructuredPostal() {
38907cf50494501938f175d288077145acf49da8f171Daniel Lehmann        return mMimeTypeIdStructuredPostal;
38917cf50494501938f175d288077145acf49da8f171Daniel Lehmann    }
38927cf50494501938f175d288077145acf49da8f171Daniel Lehmann
38932a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForOrganization() {
38942a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdOrganization;
38952a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
38962a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
38972a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForIm() {
38982a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdIm;
38992a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
39002a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
39012a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForEmail() {
39022a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdEmail;
39032a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
39042a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
39057cf50494501938f175d288077145acf49da8f171Daniel Lehmann    public long getMimeTypeIdForPhone() {
39067cf50494501938f175d288077145acf49da8f171Daniel Lehmann        return mMimeTypeIdPhone;
39077cf50494501938f175d288077145acf49da8f171Daniel Lehmann    }
39087cf50494501938f175d288077145acf49da8f171Daniel Lehmann
3909a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov    public long getMimeTypeIdForSip() {
3910a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov        return mMimeTypeIdSip;
3911a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov    }
3912a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov
39132a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public int getDisplayNameSourceForMimeTypeId(int mimeTypeId) {
39142a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        if (mimeTypeId == mMimeTypeIdStructuredName) {
39152a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.STRUCTURED_NAME;
39162a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdEmail) {
39172a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.EMAIL;
39182a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdPhone) {
39192a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.PHONE;
39202a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdOrganization) {
39212a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.ORGANIZATION;
39222a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdNickname) {
39232a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.NICKNAME;
39242a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else {
39252a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.UNDEFINED;
39262a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        }
39272a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
39282a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
3929b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3930ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Find the mimetype for the given {@link Data#_ID}.
3931b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3932b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getDataMimeType(long dataId) {
393378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mDataMimetypeQuery == null) {
393478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mDataMimetypeQuery = getWritableDatabase().compileStatement(
393578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + MimetypesColumns.MIMETYPE +
393678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.DATA_JOIN_MIMETYPES +
393778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + Tables.DATA + "." + Data._ID + "=?");
393878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3939b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
3940b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
3941b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mDataMimetypeQuery, 1, dataId);
3942b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mDataMimetypeQuery.simpleQueryForString();
3943b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
3944b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
3945b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
3946b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
3947b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3948b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3949b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3950b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3951b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Find the mime-type for the given {@link Activities#_ID}.
3952b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3953b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getActivityMimeType(long activityId) {
395478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mActivitiesMimetypeQuery == null) {
395578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mActivitiesMimetypeQuery = getWritableDatabase().compileStatement(
395678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + MimetypesColumns.MIMETYPE +
395778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.ACTIVITIES_JOIN_MIMETYPES +
395878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + Tables.ACTIVITIES + "." + Activities._ID + "=?");
395978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3960b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
3961b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
3962b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mActivitiesMimetypeQuery, 1, activityId);
3963b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mActivitiesMimetypeQuery.simpleQueryForString();
3964b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
3965b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
3966b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
3967b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
3968b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3969b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
39706bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov
39716bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov    /**
3972d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Update {@link Contacts#IN_VISIBLE_GROUP} for all contacts.
3973ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     */
3974ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public void updateAllVisible() {
3975385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        updateCustomContactVisibility(getWritableDatabase(), "");
3976ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
3977ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
3978ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    /**
3979f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov     * Updates contact visibility and return true iff the visibility was actually changed.
3980f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov     */
3981bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov    public boolean updateContactVisibleOnlyIfChanged(TransactionContext txContext, long contactId) {
3982bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov        return updateContactVisible(txContext, contactId, true);
3983f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    }
3984f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
3985f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    /**
3986385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     * Update {@link Contacts#IN_VISIBLE_GROUP} and
3987385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     * {@link Tables#DEFAULT_DIRECTORY} for a specific contact.
3988ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     */
3989bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov    public void updateContactVisible(TransactionContext txContext, long contactId) {
3990bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov        updateContactVisible(txContext, contactId, false);
3991f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    }
3992f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
3993bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov    public boolean updateContactVisible(
3994bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov            TransactionContext txContext, long contactId, boolean onlyIfChanged) {
39954394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
3996f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        updateCustomContactVisibility(db, " AND " + Contacts._ID + "=" + contactId);
3997385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3998385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        String contactIdAsString = String.valueOf(contactId);
3999385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        long mimetype = getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
4000385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
4001385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // The contact will be included in the default directory if contains
4002d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        // a raw contact that is in any group or in an account that
4003385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // does not have any AUTO_ADD groups.
4004f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        boolean newVisibility = DatabaseUtils.longForQuery(db,
4005385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "SELECT EXISTS (" +
4006385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts.CONTACT_ID +
4007385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
4008385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " JOIN " + Tables.DATA +
4009385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   ON (" + RawContactsColumns.CONCRETE_ID + "="
4010385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                            + Data.RAW_CONTACT_ID + ")" +
4011385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
4012385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + DataColumns.MIMETYPE_ID + "=?" +
4013385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ") OR EXISTS (" +
4014385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts._ID +
4015385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
4016385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
4017385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND NOT EXISTS" +
4018385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        " (SELECT " + Groups._ID +
4019385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  FROM " + Tables.GROUPS +
4020385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
4021385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                                + GroupsColumns.CONCRETE_ACCOUNT_NAME +
4022385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
4023385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                                + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
402443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                        "  AND (" + RawContactsColumns.CONCRETE_DATA_SET + " = "
402543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                                + GroupsColumns.CONCRETE_DATA_SET
402643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                                + " OR " + RawContactsColumns.CONCRETE_DATA_SET + " IS NULL AND "
402743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                                + GroupsColumns.CONCRETE_DATA_SET + " IS NULL)" +
4028385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  AND " + Groups.AUTO_ADD + " != 0" +
4029385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        ")" +
4030385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ") OR EXISTS (" +
4031385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts._ID +
4032385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
4033385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
4034385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL " +
4035385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL" +
403643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro                    "   AND " + RawContactsColumns.CONCRETE_DATA_SET + " IS NULL" +
4037385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ")",
4038385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                new String[] {
4039385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    contactIdAsString,
40406c47e208236a62c55f396116e087331e05e148f3Dmitri Plotnikov                    String.valueOf(mimetype),
4041385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    contactIdAsString,
40426c47e208236a62c55f396116e087331e05e148f3Dmitri Plotnikov                    contactIdAsString
4043f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                }) != 0;
4044385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
4045f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        if (onlyIfChanged) {
4046f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov            boolean oldVisibility = isContactInDefaultDirectory(db, contactId);
4047f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov            if (oldVisibility == newVisibility) {
4048f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                return false;
4049f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov            }
4050f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        }
4051f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
4052f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        if (newVisibility) {
4053385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY + " VALUES(?)",
4054385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    new String[] { contactIdAsString });
4055bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov            txContext.invalidateSearchIndexForContact(contactId);
4056385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        } else {
4057bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov            db.execSQL("DELETE FROM " + Tables.DEFAULT_DIRECTORY +
4058bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov                        " WHERE " + Contacts._ID + "=?",
4059bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov                    new String[] { contactIdAsString });
4060bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov            db.execSQL("DELETE FROM " + Tables.SEARCH_INDEX +
4061bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov                        " WHERE " + SearchIndexColumns.CONTACT_ID + "=CAST(? AS int)",
4062385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    new String[] { contactIdAsString });
4063385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        }
4064f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        return true;
4065f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    }
4066f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
4067f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    public boolean isContactInDefaultDirectory(SQLiteDatabase db, long contactId) {
4068f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        if (mContactInDefaultDirectoryQuery == null) {
4069f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov            mContactInDefaultDirectoryQuery = db.compileStatement(
4070f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                    "SELECT EXISTS (" +
4071f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                            "SELECT 1 FROM " + Tables.DEFAULT_DIRECTORY +
4072f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                            " WHERE " + Contacts._ID + "=?)");
4073f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        }
4074f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        mContactInDefaultDirectoryQuery.bindLong(1, contactId);
4075f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        return mContactInDefaultDirectoryQuery.simpleQueryForLong() != 0;
4076385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    }
40774394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
4078385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    private void updateCustomContactVisibility(SQLiteDatabase db, String selection) {
4079ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        final long groupMembershipMimetypeId = getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
40804394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        String[] selectionArgs = new String[]{String.valueOf(groupMembershipMimetypeId)};
40814394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
40824394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // First delete what needs to be deleted, then insert what needs to be added.
40834394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // Since flash writes are very expensive, this approach is much better than
40844394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // delete-all-insert-all.
40854394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.VISIBLE_CONTACTS +
40864394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " WHERE " + "_id NOT IN" +
40874394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        "(SELECT " + Contacts._ID +
40884394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        " FROM " + Tables.CONTACTS +
40894394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        " WHERE (" + Clauses.CONTACT_IS_VISIBLE + ")=1) " + selection,
40904394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                selectionArgs);
4091fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
40924394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.VISIBLE_CONTACTS +
40934394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " SELECT " + Contacts._ID +
40944394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " FROM " + Tables.CONTACTS +
40954394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " WHERE " + Contacts._ID +
40964394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " NOT IN " + Tables.VISIBLE_CONTACTS +
40974394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                           " AND (" + Clauses.CONTACT_IS_VISIBLE + ")=1 " + selection,
40984394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                selectionArgs);
4099ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
4100ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
4101ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    /**
4102d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Returns contact ID for the given contact or zero if it is NULL.
41036bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov     */
4104d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    public long getContactId(long rawContactId) {
410578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mContactIdQuery == null) {
410678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mContactIdQuery = getWritableDatabase().compileStatement(
410778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + RawContacts.CONTACT_ID +
410878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
410978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts._ID + "=?");
411078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
41116bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        try {
4112d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov            DatabaseUtils.bindObjectToProgram(mContactIdQuery, 1, rawContactId);
4113d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov            return mContactIdQuery.simpleQueryForLong();
41146bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        } catch (SQLiteDoneException e) {
4115a3bd0246ca3741877488bca7aadd91c79b2fd8d2Fred Quintana            // No valid mapping found, so return 0
41166bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov            return 0;
41176bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        }
41186bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov    }
411961bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov
41205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov    public int getAggregationMode(long rawContactId) {
412178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mAggregationModeQuery == null) {
412278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mAggregationModeQuery = getWritableDatabase().compileStatement(
412378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + RawContacts.AGGREGATION_MODE +
412478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
412578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts._ID + "=?");
412678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
4127f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        try {
41285ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov            DatabaseUtils.bindObjectToProgram(mAggregationModeQuery, 1, rawContactId);
4129f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            return (int)mAggregationModeQuery.simpleQueryForLong();
4130f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        } catch (SQLiteDoneException e) {
41316cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov            // No valid row found, so return "disabled"
41326cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov            return RawContacts.AGGREGATION_MODE_DISABLED;
4133f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
4134f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
4135f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
4136892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    public void buildPhoneLookupAndContactQuery(
4137892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            SQLiteQueryBuilder qb, String normalizedNumber, String numberE164) {
4138892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        String minMatch = PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber);
4139e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        StringBuilder sb = new StringBuilder();
414036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        appendPhoneLookupTables(sb, minMatch, true);
4141e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        qb.setTables(sb.toString());
4142e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
4143e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb = new StringBuilder();
4144892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        appendPhoneLookupSelection(sb, normalizedNumber, numberE164);
4145e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        qb.appendWhere(sb.toString());
4146bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    }
4147bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
414858795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda    /**
414958795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda     * Adds query for selecting the contact with the given {@code sipAddress} to the given
415058795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda     * {@link StringBuilder}.
415158795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda     *
415258795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda     * @return the query arguments to be passed in with the query
415358795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda     */
415458795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda    public String[] buildSipContactQuery(StringBuilder sb, String sipAddress) {
415558795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda        sb.append("upper(");
415658795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda        sb.append(Data.DATA1);
415758795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda        sb.append(")=upper(?) AND ");
415858795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda        sb.append(DataColumns.MIMETYPE_ID);
415958795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda        sb.append("=");
416058795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda        sb.append(Long.toString(getMimeTypeIdForSip()));
416158795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda        // Return the arguments to be passed to the query.
416258795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda        return new String[]{ sipAddress };
416358795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda    }
416458795e447fada97b9594bd7ba2e3dca241487d01Flavio Lerda
4165e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    public String buildPhoneLookupAsNestedQuery(String number) {
4166e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        StringBuilder sb = new StringBuilder();
416736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        final String minMatch = PhoneNumberUtils.toCallerIDMinMatch(number);
4168e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append("(SELECT DISTINCT raw_contact_id" + " FROM ");
416936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        appendPhoneLookupTables(sb, minMatch, false);
4170e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(" WHERE ");
4171892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        appendPhoneLookupSelection(sb, number, null);
4172e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(")");
4173e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        return sb.toString();
4174e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    }
4175e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
417636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    private void appendPhoneLookupTables(StringBuilder sb, final String minMatch,
4177e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov            boolean joinContacts) {
4178e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(Tables.RAW_CONTACTS);
4179e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        if (joinContacts) {
4180ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann            sb.append(" JOIN " + Views.CONTACTS + " contacts_view"
4181fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                    + " ON (contacts_view._id = raw_contacts.contact_id)");
4182e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        }
4183892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        sb.append(", (SELECT data_id, normalized_number, length(normalized_number) as len "
4184892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " FROM phone_lookup " + " WHERE (" + Tables.PHONE_LOOKUP + "."
4185892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + PhoneLookupColumns.MIN_MATCH + " = '");
418636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        sb.append(minMatch);
418736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        sb.append("')) AS lookup, " + Tables.DATA);
4188e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    }
4189e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
4190892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    private void appendPhoneLookupSelection(StringBuilder sb, String number, String numberE164) {
4191892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        sb.append("lookup.data_id=data._id AND data.raw_contact_id=raw_contacts._id");
4192892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        boolean hasNumberE164 = !TextUtils.isEmpty(numberE164);
4193892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        boolean hasNumber = !TextUtils.isEmpty(number);
4194892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (hasNumberE164 || hasNumber) {
4195892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            sb.append(" AND ( ");
4196892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumberE164) {
4197892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" lookup.normalized_number = ");
4198892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                DatabaseUtils.appendEscapedSQLString(sb, numberE164);
4199892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
4200892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumberE164 && hasNumber) {
4201892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" OR ");
4202892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
4203892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumber) {
4204892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                int numberLen = number.length();
4205892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" lookup.len <= ");
4206892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(numberLen);
4207892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" AND substr(");
4208892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                DatabaseUtils.appendEscapedSQLString(sb, number);
4209892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(',');
4210892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(numberLen);
4211892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" - lookup.len + 1) = lookup.normalized_number");
42121bc8603830a07b4ff641bf74227c654c99a8473bDave Santoro
421334984173c94fffb45710673f4f92150b87134ce4Shaopeng Jia                // Some countries (e.g. Brazil) can have incoming calls which contain only the local
421434984173c94fffb45710673f4f92150b87134ce4Shaopeng Jia                // number (no country calling code and no area code). This case is handled below.
421534984173c94fffb45710673f4f92150b87134ce4Shaopeng Jia                // Details see b/5197612.
42161bc8603830a07b4ff641bf74227c654c99a8473bDave Santoro                // This also handles a Gingerbread -> ICS upgrade issue; see b/5638376.
42171bc8603830a07b4ff641bf74227c654c99a8473bDave Santoro                sb.append(" OR (");
42181bc8603830a07b4ff641bf74227c654c99a8473bDave Santoro                sb.append(" lookup.len > ");
42191bc8603830a07b4ff641bf74227c654c99a8473bDave Santoro                sb.append(numberLen);
42201bc8603830a07b4ff641bf74227c654c99a8473bDave Santoro                sb.append(" AND substr(lookup.normalized_number,");
42211bc8603830a07b4ff641bf74227c654c99a8473bDave Santoro                sb.append("lookup.len + 1 - ");
42221bc8603830a07b4ff641bf74227c654c99a8473bDave Santoro                sb.append(numberLen);
42231bc8603830a07b4ff641bf74227c654c99a8473bDave Santoro                sb.append(") = ");
42241bc8603830a07b4ff641bf74227c654c99a8473bDave Santoro                DatabaseUtils.appendEscapedSQLString(sb, number);
42251bc8603830a07b4ff641bf74227c654c99a8473bDave Santoro                sb.append(")");
4226892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
4227892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            sb.append(')');
4228892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
422936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    }
423036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
423136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    public String getUseStrictPhoneNumberComparisonParameter() {
423236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        return mUseStrictPhoneNumberComparison ? "1" : "0";
4233fb362d1a5df250a49fad06db323b0d41fe0e3757Dmitri Plotnikov    }
4234bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
4235619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    /**
4236b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     * Loads common nickname mappings into the database.
4237b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     */
4238b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private void loadNicknameLookupTable(SQLiteDatabase db) {
423951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NICKNAME_LOOKUP);
424051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
424128f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar        String[] strings = mContext.getResources().getStringArray(
424228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar                com.android.internal.R.array.common_nicknames);
4243b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        if (strings == null || strings.length == 0) {
4244b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            return;
4245b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
4246b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
4247b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        SQLiteStatement nicknameLookupInsert = db.compileStatement("INSERT INTO "
4248b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                + Tables.NICKNAME_LOOKUP + "(" + NicknameLookupColumns.NAME + ","
4249b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                + NicknameLookupColumns.CLUSTER + ") VALUES (?,?)");
4250b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
425151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
425251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            for (int clusterId = 0; clusterId < strings.length; clusterId++) {
425351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                String[] names = strings[clusterId].split(",");
425451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                for (int j = 0; j < names.length; j++) {
425551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    String name = NameNormalizer.normalize(names[j]);
425651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    try {
425751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        DatabaseUtils.bindObjectToProgram(nicknameLookupInsert, 1, name);
425851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        DatabaseUtils.bindObjectToProgram(nicknameLookupInsert, 2,
425951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                                String.valueOf(clusterId));
426051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        nicknameLookupInsert.executeInsert();
426151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    } catch (SQLiteException e) {
426251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
426351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        // Print the exception and keep going - this is not a fatal error
426451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        Log.e(TAG, "Cannot insert nickname: " + names[j], e);
426551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    }
4266b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                }
4267b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            }
426851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
426951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            nicknameLookupInsert.close();
4270b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
4271b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    }
4272b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
4273f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    public static void copyStringValue(ContentValues toValues, String toKey,
4274f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            ContentValues fromValues, String fromKey) {
4275f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        if (fromValues.containsKey(fromKey)) {
4276f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            toValues.put(toKey, fromValues.getAsString(fromKey));
4277f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
4278f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
4279f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
4280f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    public static void copyLongValue(ContentValues toValues, String toKey,
4281f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            ContentValues fromValues, String fromKey) {
4282f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        if (fromValues.containsKey(fromKey)) {
4283f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            long longValue;
4284f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            Object value = fromValues.get(fromKey);
4285f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            if (value instanceof Boolean) {
4286f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                if ((Boolean)value) {
4287f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                    longValue = 1;
4288f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                } else {
4289f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                    longValue = 0;
4290f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                }
42911b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov            } else if (value instanceof String) {
42921b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov                longValue = Long.parseLong((String)value);
4293f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            } else {
42941b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov                longValue = ((Number)value).longValue();
4295f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            }
4296f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            toValues.put(toKey, longValue);
4297f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
4298f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
4299f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
430035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    public SyncStateContentProviderHelper getSyncState() {
430135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        return mSyncState;
430235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    }
4303c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
4304c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    /**
4305c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     * Delete the aggregate contact if it has no constituent raw contacts other
4306c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     * than the supplied one.
4307c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     */
4308c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    public void removeContactIfSingleton(long rawContactId) {
4309c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
4310c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
4311c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        // Obtain contact ID from the supplied raw contact ID
4312c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        String contactIdFromRawContactId = "(SELECT " + RawContacts.CONTACT_ID + " FROM "
4313c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=" + rawContactId + ")";
4314c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
4315c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        // Find other raw contacts in the same aggregate contact
4316c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        String otherRawContacts = "(SELECT contacts1." + RawContacts._ID + " FROM "
4317c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + Tables.RAW_CONTACTS + " contacts1 JOIN " + Tables.RAW_CONTACTS + " contacts2 ON ("
4318c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "contacts1." + RawContacts.CONTACT_ID + "=contacts2." + RawContacts.CONTACT_ID
4319c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + ") WHERE contacts1." + RawContacts._ID + "!=" + rawContactId + ""
4320c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " AND contacts2." + RawContacts._ID + "=" + rawContactId + ")";
4321c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
4322c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CONTACTS
4323c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " WHERE " + Contacts._ID + "=" + contactIdFromRawContactId
4324c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " AND NOT EXISTS " + otherRawContacts + ";");
4325c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    }
43264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
43274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    /**
4328b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     * Returns the value from the {@link Tables#PROPERTIES} table.
4329b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     */
4330b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public String getProperty(String key, String defaultValue) {
4331b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        Cursor cursor = getReadableDatabase().query(Tables.PROPERTIES,
4332b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                new String[]{PropertiesColumns.PROPERTY_VALUE},
4333b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_KEY + "=?",
4334b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                new String[]{key}, null, null, null);
4335b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        String value = null;
4336b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        try {
4337b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            if (cursor.moveToFirst()) {
4338b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                value = cursor.getString(0);
4339b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            }
4340b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        } finally {
4341b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            cursor.close();
4342b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        }
4343b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
4344b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        return value != null ? value : defaultValue;
4345b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
4346b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
4347b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    /**
4348b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     * Stores a key-value pair in the {@link Tables#PROPERTIES} table.
4349b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     */
4350b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public void setProperty(String key, String value) {
43513d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        setProperty(getWritableDatabase(), key, value);
43523d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
43533d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
43543d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    private void setProperty(SQLiteDatabase db, String key, String value) {
4355b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ContentValues values = new ContentValues();
4356b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        values.put(PropertiesColumns.PROPERTY_KEY, key);
4357b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        values.put(PropertiesColumns.PROPERTY_VALUE, value);
43583d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        db.replace(Tables.PROPERTIES, null, values);
4359b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
4360b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
4361b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    /**
4362ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov     * Test if any of the columns appear in the given projection.
4363ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov     */
4364ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov    public boolean isInProjection(String[] projection, String... columns) {
436582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        if (projection == null) {
436682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            return true;
436782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        }
4368ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov
436982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        // Optimized for a single-column test
437082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        if (columns.length == 1) {
437182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            String column = columns[0];
437282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            for (String test : projection) {
437382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                if (column.equals(test)) {
437482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                    return true;
437582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                }
437682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            }
437782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        } else {
437882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            for (String test : projection) {
437982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                for (String column : columns) {
4380ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                    if (column.equals(test)) {
4381ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                        return true;
4382ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                    }
4383ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                }
4384ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov            }
4385ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov        }
4386ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov        return false;
43874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
4388fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
4389fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    /**
4390fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * Returns a detailed exception message for the supplied URI.  It includes the calling
4391fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * user and calling package(s).
4392fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     */
4393fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    public String exceptionMessage(Uri uri) {
4394fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        return exceptionMessage(null, uri);
4395fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    }
4396fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
4397fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    /**
4398fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * Returns a detailed exception message for the supplied URI.  It includes the calling
4399fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * user and calling package(s).
4400fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     */
4401fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    public String exceptionMessage(String message, Uri uri) {
4402fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        StringBuilder sb = new StringBuilder();
4403fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (message != null) {
4404fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(message).append("; ");
4405fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
4406fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        sb.append("URI: ").append(uri);
4407fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        final PackageManager pm = mContext.getPackageManager();
4408fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        int callingUid = Binder.getCallingUid();
4409fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        sb.append(", calling user: ");
4410fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        String userName = pm.getNameForUid(callingUid);
4411fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (userName != null) {
4412fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(userName);
4413fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        } else {
4414fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(callingUid);
4415fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
4416fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
4417fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        final String[] callerPackages = pm.getPackagesForUid(callingUid);
4418fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (callerPackages != null && callerPackages.length > 0) {
4419fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            if (callerPackages.length == 1) {
4420fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(", calling package:");
4421fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(callerPackages[0]);
4422fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            } else {
4423fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(", calling package is one of: [");
4424fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                for (int i = 0; i < callerPackages.length; i++) {
4425fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    if (i != 0) {
4426fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                        sb.append(", ");
4427fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    }
4428fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    sb.append(callerPackages[i]);
4429fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                }
4430fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append("]");
4431fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            }
4432fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
4433fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
4434fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        return sb.toString();
4435fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    }
4436892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
4437892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    protected String getCountryIso() {
4438892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        CountryDetector detector =
4439892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            (CountryDetector) mContext.getSystemService(Context.COUNTRY_DETECTOR);
4440892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        return detector.detectCountry().getCountryIso();
4441892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    }
444278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
444378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void deleteStatusUpdate(long dataId) {
444478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mStatusUpdateDelete == null) {
444578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateDelete = getWritableDatabase().compileStatement(
444678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "DELETE FROM " + Tables.STATUS_UPDATES +
444778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + StatusUpdatesColumns.DATA_ID + "=?");
444878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
444978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateDelete.bindLong(1, dataId);
445078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateDelete.execute();
445178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
445278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
445378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void replaceStatusUpdate(Long dataId, long timestamp, String status, String resPackage,
44540bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann            Integer iconResource, Integer labelResource) {
445578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mStatusUpdateReplace == null) {
445678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateReplace = getWritableDatabase().compileStatement(
445778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "("
445878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdatesColumns.DATA_ID + ", "
445978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_TIMESTAMP + ","
446078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS + ","
446178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_RES_PACKAGE + ","
446278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_ICON + ","
446378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_LABEL + ")" +
446478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " VALUES (?,?,?,?,?,?)");
446578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
446678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace.bindLong(1, dataId);
446778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace.bindLong(2, timestamp);
446878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mStatusUpdateReplace, 3, status);
446978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mStatusUpdateReplace, 4, resPackage);
447078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindLong(mStatusUpdateReplace, 5, iconResource);
447178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindLong(mStatusUpdateReplace, 6, labelResource);
447278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace.execute();
447378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
447478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
44750bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann    public void insertStatusUpdate(Long dataId, String status, String resPackage,
44760bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann            Integer iconResource, Integer labelResource) {
447778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mStatusUpdateInsert == null) {
447878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateInsert = getWritableDatabase().compileStatement(
447978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT INTO " + Tables.STATUS_UPDATES + "("
448078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdatesColumns.DATA_ID + ", "
448178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS + ","
448278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_RES_PACKAGE + ","
448378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_ICON + ","
448478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_LABEL + ")" +
448578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " VALUES (?,?,?,?,?)");
448678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
448778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        try {
448878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateInsert.bindLong(1, dataId);
448978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateInsert, 2, status);
449078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateInsert, 3, resPackage);
449178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusUpdateInsert, 4, iconResource);
449278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusUpdateInsert, 5, labelResource);
449378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateInsert.executeInsert();
449478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        } catch (SQLiteConstraintException e) {
449578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            // The row already exists - update it
449678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            if (mStatusUpdateAutoTimestamp == null) {
449778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                mStatusUpdateAutoTimestamp = getWritableDatabase().compileStatement(
449878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        "UPDATE " + Tables.STATUS_UPDATES +
449978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?,"
450078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + StatusUpdates.STATUS + "=?" +
450178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"
450278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + " AND " + StatusUpdates.STATUS + "!=?");
450378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            }
450478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
450578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            long timestamp = System.currentTimeMillis();
450678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateAutoTimestamp.bindLong(1, timestamp);
450778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateAutoTimestamp, 2, status);
450878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateAutoTimestamp.bindLong(3, dataId);
450978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateAutoTimestamp, 4, status);
451078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateAutoTimestamp.execute();
451178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
451278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            if (mStatusAttributionUpdate == null) {
451378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                mStatusAttributionUpdate = getWritableDatabase().compileStatement(
451478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        "UPDATE " + Tables.STATUS_UPDATES +
451578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?,"
451678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + StatusUpdates.STATUS_ICON + "=?,"
451778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + StatusUpdates.STATUS_LABEL + "=?" +
451878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " WHERE " + StatusUpdatesColumns.DATA_ID + "=?");
451978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            }
452078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusAttributionUpdate, 1, resPackage);
452178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusAttributionUpdate, 2, iconResource);
452278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusAttributionUpdate, 3, labelResource);
452378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusAttributionUpdate.bindLong(4, dataId);
452478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusAttributionUpdate.execute();
452578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
452678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
452778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
452878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /**
452978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Resets the {@link RawContacts#NAME_VERIFIED} flag to 0 on all other raw
453078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * contacts in the same aggregate
453178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
453278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void resetNameVerifiedForOtherRawContacts(long rawContactId) {
453378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mResetNameVerifiedForOtherRawContacts == null) {
453478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mResetNameVerifiedForOtherRawContacts = getWritableDatabase().compileStatement(
453578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.RAW_CONTACTS +
453678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + RawContacts.NAME_VERIFIED + "=0" +
453778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=(" +
453878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            "SELECT " + RawContacts.CONTACT_ID +
453978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " FROM " + Tables.RAW_CONTACTS +
454078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " WHERE " + RawContacts._ID + "=?)" +
454178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " AND " + RawContacts._ID + "!=?");
454278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
454378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts.bindLong(1, rawContactId);
454478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts.bindLong(2, rawContactId);
454578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts.execute();
454678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
454778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
45488ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov    private interface RawContactNameQuery {
45498ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final String RAW_SQL =
45508ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                "SELECT "
45518ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        + DataColumns.MIMETYPE_ID + ","
45528ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        + Data.IS_PRIMARY + ","
45538ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        + Data.DATA1 + ","
45548ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        + Data.DATA2 + ","
45558ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        + Data.DATA3 + ","
45568ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        + Data.DATA4 + ","
45578ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        + Data.DATA5 + ","
45588ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        + Data.DATA6 + ","
45598ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        + Data.DATA7 + ","
45608ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        + Data.DATA8 + ","
45618ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        + Data.DATA9 + ","
45628ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        + Data.DATA10 + ","
45638ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        + Data.DATA11 +
45648ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                " FROM " + Tables.DATA +
45658ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                " WHERE " + Data.RAW_CONTACT_ID + "=?" +
45668ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        " AND (" + Data.DATA1 + " NOT NULL OR " +
45678ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                                Organization.TITLE + " NOT NULL)";
45688ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
45698ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int MIMETYPE = 0;
45708ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int IS_PRIMARY = 1;
45718ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int DATA1 = 2;
45728ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int GIVEN_NAME = 3;                         // data2
45738ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int FAMILY_NAME = 4;                        // data3
45748ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int PREFIX = 5;                             // data4
45758ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int TITLE = 5;                              // data4
45768ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int MIDDLE_NAME = 6;                        // data5
45778ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int SUFFIX = 7;                             // data6
45788ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int PHONETIC_GIVEN_NAME = 8;                // data7
45798ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int PHONETIC_MIDDLE_NAME = 9;               // data8
45808ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int ORGANIZATION_PHONETIC_NAME = 9;         // data8
45818ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int PHONETIC_FAMILY_NAME = 10;              // data9
45828ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int FULL_NAME_STYLE = 11;                   // data10
45838ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int ORGANIZATION_PHONETIC_NAME_STYLE = 11;  // data10
45848ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        public static final int PHONETIC_NAME_STYLE = 12;               // data11
45858ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov    }
45868ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
45878ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov    /**
45888ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov     * Updates a raw contact display name based on data rows, e.g. structured name,
45898ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov     * organization, email etc.
45908ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov     */
45918ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov    public void updateRawContactDisplayName(SQLiteDatabase db, long rawContactId) {
45928ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        if (mNameSplitter == null) {
45938ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            createNameSplitter();
45948ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        }
45958ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
45968ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        int bestDisplayNameSource = DisplayNameSources.UNDEFINED;
45978ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        NameSplitter.Name bestName = null;
45988ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        String bestDisplayName = null;
45998ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        String bestPhoneticName = null;
46008ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        int bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED;
46018ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
46028ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        mSelectionArgs1[0] = String.valueOf(rawContactId);
46038ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        Cursor c = db.rawQuery(RawContactNameQuery.RAW_SQL, mSelectionArgs1);
46048ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        try {
46058ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            while (c.moveToNext()) {
46068ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                int mimeType = c.getInt(RawContactNameQuery.MIMETYPE);
46078ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                int source = getDisplayNameSourceForMimeTypeId(mimeType);
46088ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                if (source < bestDisplayNameSource || source == DisplayNameSources.UNDEFINED) {
46098ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    continue;
46108ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                }
46118ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
46128ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                if (source == bestDisplayNameSource
46138ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        && c.getInt(RawContactNameQuery.IS_PRIMARY) == 0) {
46148ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    continue;
46158ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                }
46168ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
46178ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                if (mimeType == getMimeTypeIdForStructuredName()) {
46188ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    NameSplitter.Name name;
46198ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    if (bestName != null) {
46208ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        name = new NameSplitter.Name();
46218ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    } else {
46228ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        name = mName;
46238ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        name.clear();
46248ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    }
46258ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    name.prefix = c.getString(RawContactNameQuery.PREFIX);
46268ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    name.givenNames = c.getString(RawContactNameQuery.GIVEN_NAME);
46278ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    name.middleName = c.getString(RawContactNameQuery.MIDDLE_NAME);
46288ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    name.familyName = c.getString(RawContactNameQuery.FAMILY_NAME);
46298ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    name.suffix = c.getString(RawContactNameQuery.SUFFIX);
46308ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    name.fullNameStyle = c.isNull(RawContactNameQuery.FULL_NAME_STYLE)
46318ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                            ? FullNameStyle.UNDEFINED
46328ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                            : c.getInt(RawContactNameQuery.FULL_NAME_STYLE);
46338ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    name.phoneticFamilyName = c.getString(RawContactNameQuery.PHONETIC_FAMILY_NAME);
46348ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    name.phoneticMiddleName = c.getString(RawContactNameQuery.PHONETIC_MIDDLE_NAME);
46358ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    name.phoneticGivenName = c.getString(RawContactNameQuery.PHONETIC_GIVEN_NAME);
46368ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    name.phoneticNameStyle = c.isNull(RawContactNameQuery.PHONETIC_NAME_STYLE)
46378ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                            ? PhoneticNameStyle.UNDEFINED
46388ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                            : c.getInt(RawContactNameQuery.PHONETIC_NAME_STYLE);
46398ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    if (!name.isEmpty()) {
46408ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        bestDisplayNameSource = source;
46418ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        bestName = name;
46428ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    }
46438ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                } else if (mimeType == getMimeTypeIdForOrganization()) {
46448ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    mCharArrayBuffer.sizeCopied = 0;
46458ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    c.copyStringToBuffer(RawContactNameQuery.DATA1, mCharArrayBuffer);
46468ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    if (mCharArrayBuffer.sizeCopied != 0) {
46478ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        bestDisplayNameSource = source;
46488ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        bestDisplayName = new String(mCharArrayBuffer.data, 0,
46498ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                                mCharArrayBuffer.sizeCopied);
46508ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        bestPhoneticName = c.getString(
46518ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                                RawContactNameQuery.ORGANIZATION_PHONETIC_NAME);
46528ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        bestPhoneticNameStyle =
46538ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                                c.isNull(RawContactNameQuery.ORGANIZATION_PHONETIC_NAME_STYLE)
46548ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                                   ? PhoneticNameStyle.UNDEFINED
46558ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                                   : c.getInt(RawContactNameQuery.ORGANIZATION_PHONETIC_NAME_STYLE);
46568ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    } else {
46578ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        c.copyStringToBuffer(RawContactNameQuery.TITLE, mCharArrayBuffer);
46588ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        if (mCharArrayBuffer.sizeCopied != 0) {
46598ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                            bestDisplayNameSource = source;
46608ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                            bestDisplayName = new String(mCharArrayBuffer.data, 0,
46618ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                                    mCharArrayBuffer.sizeCopied);
46628ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                            bestPhoneticName = null;
46638ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                            bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED;
46648ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        }
46658ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    }
46668ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                } else {
46678ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    // Display name is at DATA1 in all other types.
46688ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    // This is ensured in the constructor.
46698ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
46708ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    mCharArrayBuffer.sizeCopied = 0;
46718ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    c.copyStringToBuffer(RawContactNameQuery.DATA1, mCharArrayBuffer);
46728ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    if (mCharArrayBuffer.sizeCopied != 0) {
46738ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        bestDisplayNameSource = source;
46748ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        bestDisplayName = new String(mCharArrayBuffer.data, 0,
46758ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                                mCharArrayBuffer.sizeCopied);
46768ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        bestPhoneticName = null;
46778ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED;
46788ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    }
46798ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                }
46808ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            }
46818ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
46828ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        } finally {
46838ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            c.close();
46848ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        }
46858ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
46868ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        String displayNamePrimary;
46878ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        String displayNameAlternative;
468855e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        String sortNamePrimary;
468955e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        String sortNameAlternative;
46908ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        String sortKeyPrimary = null;
46918ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        String sortKeyAlternative = null;
46928ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        int displayNameStyle = FullNameStyle.UNDEFINED;
46938ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
46948ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        if (bestDisplayNameSource == DisplayNameSources.STRUCTURED_NAME) {
46958ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            displayNameStyle = bestName.fullNameStyle;
46968ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            if (displayNameStyle == FullNameStyle.CJK
46978ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    || displayNameStyle == FullNameStyle.UNDEFINED) {
46988ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                displayNameStyle = mNameSplitter.getAdjustedFullNameStyle(displayNameStyle);
46998ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                bestName.fullNameStyle = displayNameStyle;
47008ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            }
47018ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
470255e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            displayNamePrimary = mNameSplitter.join(bestName, true, true);
470355e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            displayNameAlternative = mNameSplitter.join(bestName, false, true);
470455e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov
470555e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            if (TextUtils.isEmpty(bestName.prefix)) {
470655e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov                sortNamePrimary = displayNamePrimary;
470755e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov                sortNameAlternative = displayNameAlternative;
470855e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            } else {
470955e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov                sortNamePrimary = mNameSplitter.join(bestName, true, false);
471055e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov                sortNameAlternative = mNameSplitter.join(bestName, false, false);
471155e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            }
47128ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
47138ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            bestPhoneticName = mNameSplitter.joinPhoneticName(bestName);
47148ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            bestPhoneticNameStyle = bestName.phoneticNameStyle;
47158ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        } else {
47168ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            displayNamePrimary = displayNameAlternative = bestDisplayName;
471755e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            sortNamePrimary = sortNameAlternative = bestDisplayName;
47188ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        }
47198ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
47208ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        if (bestPhoneticName != null) {
47218ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            sortKeyPrimary = sortKeyAlternative = bestPhoneticName;
47228ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            if (bestPhoneticNameStyle == PhoneticNameStyle.UNDEFINED) {
47238ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                bestPhoneticNameStyle = mNameSplitter.guessPhoneticNameStyle(bestPhoneticName);
47248ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            }
47258ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        } else {
47268ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            if (displayNameStyle == FullNameStyle.UNDEFINED) {
47278ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                displayNameStyle = mNameSplitter.guessFullNameStyle(bestDisplayName);
47288ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                if (displayNameStyle == FullNameStyle.UNDEFINED
47298ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        || displayNameStyle == FullNameStyle.CJK) {
47308ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    displayNameStyle = mNameSplitter.getAdjustedNameStyleBasedOnPhoneticNameStyle(
47318ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                            displayNameStyle, bestPhoneticNameStyle);
47328ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                }
47338ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                displayNameStyle = mNameSplitter.getAdjustedFullNameStyle(displayNameStyle);
47348ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            }
47358ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            if (displayNameStyle == FullNameStyle.CHINESE ||
47368ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                    displayNameStyle == FullNameStyle.CJK) {
47378ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                sortKeyPrimary = sortKeyAlternative =
47388ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov                        ContactLocaleUtils.getIntance().getSortKey(
473955e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov                                sortNamePrimary, displayNameStyle);
47408ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov            }
47418ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        }
47428ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
47438ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        if (sortKeyPrimary == null) {
474455e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            sortKeyPrimary = sortNamePrimary;
474555e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            sortKeyAlternative = sortNameAlternative;
47468ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov        }
47478ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov
474878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mRawContactDisplayNameUpdate == null) {
474955e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov            mRawContactDisplayNameUpdate = db.compileStatement(
475078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.RAW_CONTACTS +
475178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " +
475278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.DISPLAY_NAME_SOURCE + "=?," +
475378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.DISPLAY_NAME_PRIMARY + "=?," +
475478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," +
475578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.PHONETIC_NAME + "=?," +
475678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.PHONETIC_NAME_STYLE + "=?," +
475778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.SORT_KEY_PRIMARY + "=?," +
475878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.SORT_KEY_ALTERNATIVE + "=?" +
475978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts._ID + "=?");
476078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
476155e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov
476255e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        mRawContactDisplayNameUpdate.bindLong(1, bestDisplayNameSource);
476378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 2, displayNamePrimary);
476478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 3, displayNameAlternative);
476555e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 4, bestPhoneticName);
476655e5cbf566edd89fc55f4a7f0ef2847084da9b16Dmitri Plotnikov        mRawContactDisplayNameUpdate.bindLong(5, bestPhoneticNameStyle);
476778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 6, sortKeyPrimary);
476878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 7, sortKeyAlternative);
476978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate.bindLong(8, rawContactId);
477078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate.execute();
477178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
477278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
477378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /*
477478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Sets the given dataId record in the "data" table to primary, and resets all data records of
477578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * the same mimetype and under the same contact to not be primary.
477678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     *
477778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * @param dataId the id of the data record to be set to primary. Pass -1 to clear the primary
477878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * flag of all data items of this raw contacts
477978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
478078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) {
478178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mSetPrimaryStatement == null) {
478278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mSetPrimaryStatement = getWritableDatabase().compileStatement(
478378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.DATA +
478478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + Data.IS_PRIMARY + "=(_id=?)" +
478578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=?" +
478678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "   AND " + Data.RAW_CONTACT_ID + "=?");
478778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
478878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.bindLong(1, dataId);
478978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.bindLong(2, mimeTypeId);
479078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.bindLong(3, rawContactId);
479178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.execute();
479278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
479378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
479478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /*
479578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Clears the super primary of all data items of the given raw contact. does not touch
479678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * other raw contacts of the same joined aggregate
479778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
479878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void clearSuperPrimary(long rawContactId, long mimeTypeId) {
479978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mClearSuperPrimaryStatement == null) {
480078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mClearSuperPrimaryStatement = getWritableDatabase().compileStatement(
480178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.DATA +
480278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + Data.IS_SUPER_PRIMARY + "=0" +
480378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=?" +
480478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "   AND " + Data.RAW_CONTACT_ID + "=?");
480578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
480678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement.bindLong(1, mimeTypeId);
480778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement.bindLong(2, rawContactId);
480878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement.execute();
480978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
481078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
481178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /*
481278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Sets the given dataId record in the "data" table to "super primary", and resets all data
481378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * records of the same mimetype and under the same aggregate to not be "super primary".
481478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     *
481578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * @param dataId the id of the data record to be set to primary.
481678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
481778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) {
481878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mSetSuperPrimaryStatement == null) {
481978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mSetSuperPrimaryStatement = getWritableDatabase().compileStatement(
482078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.DATA +
482178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" +
482278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=?" +
482378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "   AND " + Data.RAW_CONTACT_ID + " IN (" +
482478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            "SELECT " + RawContacts._ID +
482578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " FROM " + Tables.RAW_CONTACTS +
482678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " WHERE " + RawContacts.CONTACT_ID + " =(" +
482778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                    "SELECT " + RawContacts.CONTACT_ID +
482878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                    " FROM " + Tables.RAW_CONTACTS +
482978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                    " WHERE " + RawContacts._ID + "=?))");
483078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
483178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.bindLong(1, dataId);
483278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.bindLong(2, mimeTypeId);
483378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.bindLong(3, rawContactId);
483478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.execute();
483578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
483678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
483778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /**
483878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Inserts a record in the {@link Tables#NAME_LOOKUP} table.
483978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
484078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) {
484178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (TextUtils.isEmpty(name)) {
484278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            return;
484378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
484478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
484578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mNameLookupInsert == null) {
484678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mNameLookupInsert = getWritableDatabase().compileStatement(
484778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "("
484878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.RAW_CONTACT_ID + ","
484978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.DATA_ID + ","
485078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.NAME_TYPE + ","
485178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.NORMALIZED_NAME
485278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    + ") VALUES (?,?,?,?)");
485378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
485478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.bindLong(1, rawContactId);
485578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.bindLong(2, dataId);
485678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.bindLong(3, lookupType);
485778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mNameLookupInsert, 4, name);
485878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.executeInsert();
485978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
486078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
486178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /**
486278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element.
486378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
486478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void deleteNameLookup(long dataId) {
486578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mNameLookupDelete == null) {
486678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mNameLookupDelete = getWritableDatabase().compileStatement(
486778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "DELETE FROM " + Tables.NAME_LOOKUP +
486878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + NameLookupColumns.DATA_ID + "=?");
486978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
487078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupDelete.bindLong(1, dataId);
487178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupDelete.execute();
487278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
4873189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov
4874e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public String insertNameLookupForEmail(long rawContactId, long dataId, String email) {
4875e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (TextUtils.isEmpty(email)) {
4876e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            return null;
4877e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
4878e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
4879e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        String address = extractHandleFromEmailAddress(email);
4880e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (address == null) {
4881e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            return null;
4882e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
4883e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
4884e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        insertNameLookup(rawContactId, dataId,
4885e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov                NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address));
4886e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        return address;
4887e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
4888e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
4889e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    /**
4890e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov     * Normalizes the nickname and inserts it in the name lookup table.
4891e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov     */
4892e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) {
4893e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (TextUtils.isEmpty(nickname)) {
4894e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            return;
4895e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
4896e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
4897e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        insertNameLookup(rawContactId, dataId,
4898e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov                NameLookupType.NICKNAME, NameNormalizer.normalize(nickname));
4899e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
4900e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
49015df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov    public void insertNameLookupForPhoneticName(long rawContactId, long dataId, String familyName,
49025df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            String middleName, String givenName) {
49035df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        mSb.setLength(0);
49045df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (familyName != null) {
49055df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            mSb.append(familyName.trim());
49065df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
49075df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (middleName != null) {
49085df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            mSb.append(middleName.trim());
49095df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
49105df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (givenName != null) {
49115df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            mSb.append(givenName.trim());
49125df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
49135df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov
49145df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (mSb.length() > 0) {
49155df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            insertNameLookup(rawContactId, dataId, NameLookupType.NAME_COLLATION_KEY,
49165df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov                    NameNormalizer.normalize(mSb.toString()));
49175df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
49185df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov    }
49195df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov
4920189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov    /**
4921189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov     * Performs a query and returns true if any Data item of the raw contact with the given
4922189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov     * id and mimetype is marked as super-primary
4923189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov     */
4924189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov    public boolean rawContactHasSuperPrimary(long rawContactId, long mimeTypeId) {
4925189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        final Cursor existsCursor = getReadableDatabase().rawQuery(
4926189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                "SELECT EXISTS(SELECT 1 FROM " + Tables.DATA +
4927189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                " WHERE " + Data.RAW_CONTACT_ID + "=?" +
4928189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                " AND " + DataColumns.MIMETYPE_ID + "=?" +
4929189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                " AND " + Data.IS_SUPER_PRIMARY + "<>0)",
4930189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                new String[] { String.valueOf(rawContactId), String.valueOf(mimeTypeId) });
4931189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        try {
4932189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov            if (!existsCursor.moveToFirst()) throw new IllegalStateException();
4933189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov            return existsCursor.getInt(0) != 0;
4934189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        } finally {
4935189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov            existsCursor.close();
4936189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        }
4937189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov    }
4938e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
4939e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public String getCurrentCountryIso() {
4940e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        return mCountryMonitor.getCountryIso();
4941e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
4942f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov
4943383d8aa53aa2f74a4b71642de7df2e4b9f2242c8Dmitri Plotnikov    /* package */ String querySearchIndexContentForTest(long contactId) {
4944f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov        return DatabaseUtils.stringForQuery(getReadableDatabase(),
4945f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov                "SELECT " + SearchIndexColumns.CONTENT +
4946f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov                " FROM " + Tables.SEARCH_INDEX +
4947f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov                " WHERE " + SearchIndexColumns.CONTACT_ID + "=CAST(? AS int)",
4948f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov                new String[] { String.valueOf(contactId) });
4949f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov    }
4950f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov
4951383d8aa53aa2f74a4b71642de7df2e4b9f2242c8Dmitri Plotnikov    /* package */ String querySearchIndexTokensForTest(long contactId) {
4952f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov        return DatabaseUtils.stringForQuery(getReadableDatabase(),
4953f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov                "SELECT " + SearchIndexColumns.TOKENS +
4954f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov                " FROM " + Tables.SEARCH_INDEX +
4955f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov                " WHERE " + SearchIndexColumns.CONTACT_ID + "=CAST(? AS int)",
4956f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov                new String[] { String.valueOf(contactId) });
4957f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov    }
4958b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey}
4959