ContactsDatabaseHelper.java revision 2b07b826e208e464bbd85d4679aab956bef0bafc
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
1967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport com.android.internal.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;
2836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikovimport android.database.Cursor;
29b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.DatabaseUtils;
30f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikovimport android.database.SQLException;
31b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteDatabase;
32b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteDoneException;
33b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikovimport android.database.sqlite.SQLiteException;
34b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteOpenHelper;
35bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikovimport android.database.sqlite.SQLiteQueryBuilder;
36b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteStatement;
37892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikovimport android.location.CountryDetector;
38fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikovimport android.net.Uri;
394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikovimport android.os.Binder;
40a3bd0246ca3741877488bca7aadd91c79b2fd8d2Fred Quintanaimport android.os.Bundle;
41c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamiltonimport android.os.SystemClock;
42b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.provider.BaseColumns;
43e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.provider.CallLog.Calls;
44a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract;
45b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions;
46a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email;
47a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.GroupMembership;
48a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname;
49a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization;
50a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone;
51a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName;
52d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.Contacts;
533d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikovimport android.provider.ContactsContract.Contacts.Photo;
54de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.Data;
55d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.provider.ContactsContract.Directory;
565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.DisplayNameSources;
575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.FullNameStyle;
58ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.Groups;
59d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts;
60eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkeyimport android.provider.ContactsContract.Settings;
6182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates;
6267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.SocialContract.Activities;
63bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikovimport android.telephony.PhoneNumberUtils;
6436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikovimport android.text.TextUtils;
65b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikovimport android.text.util.Rfc822Token;
66b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikovimport android.text.util.Rfc822Tokenizer;
67b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.util.Log;
68b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
69b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport java.util.HashMap;
705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport java.util.Locale;
71b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
72b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey/**
73b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov * Database helper for contacts. Designed as a singleton to make sure that all
74b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov * {@link android.content.ContentProvider} users get the same reference.
75b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov * Provides handy methods for maintaining package and mime-type lookup tables.
76b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey */
77b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov/* package */ class ContactsDatabaseHelper extends SQLiteOpenHelper {
78b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    private static final String TAG = "ContactsDatabaseHelper";
79b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
8097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    /**
8194c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov     * Contacts DB version ranges:
8297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     * <pre>
8397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   0-98    Cupcake/Donut
8497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   100-199 Eclair
8597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   200-299 Eclair-MR1
8697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   300-349 Froyo
8797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   350-399 Gingerbread
8897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   400-499 Honeycomb
8997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     * </pre>
9097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     */
912b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov    static final int DATABASE_VERSION = 410;
92e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
93b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private static final String DATABASE_NAME = "contacts2.db";
941f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    private static final String DATABASE_PRESENCE = "presence_db";
95b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
96b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface Tables {
97d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONTACTS = "contacts";
985ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACTS = "raw_contacts";
99ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String PACKAGES = "packages";
100ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String MIMETYPES = "mimetypes";
101b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PHONE_LOOKUP = "phone_lookup";
102a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NAME_LOOKUP = "name_lookup";
103b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        public static final String AGGREGATION_EXCEPTIONS = "agg_exceptions";
104eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        public static final String SETTINGS = "settings";
105b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA = "data";
106ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String GROUPS = "groups";
1071f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        public static final String PRESENCE = "presence";
108e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        public static final String AGGREGATED_PRESENCE = "agg_presence";
109b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String NICKNAME_LOOKUP = "nickname_lookup";
110e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        public static final String CALLS = "calls";
111a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        public static final String STATUS_UPDATES = "status_updates";
112b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        public static final String PROPERTIES = "properties";
113743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        public static final String ACCOUNTS = "accounts";
1144394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        public static final String VISIBLE_CONTACTS = "visible_contacts";
115d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        public static final String DIRECTORIES = "directories";
116385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        public static final String DEFAULT_DIRECTORY = "default_directory";
117b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
118ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String DATA_JOIN_MIMETYPES = "data "
1191b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id)";
120b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
12111944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        public static final String DATA_JOIN_RAW_CONTACTS = "data "
1228e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id)";
12311944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
1245ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String DATA_JOIN_MIMETYPE_RAW_CONTACTS = "data "
125c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
126c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id)";
127bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
128e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        // NOTE: This requires late binding of GroupMembership MIME-type
129e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String RAW_CONTACTS_JOIN_SETTINGS_DATA_GROUPS = "raw_contacts "
130e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN settings ON ("
131e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_name = settings.account_name AND "
132e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_type = settings.account_type) "
133e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN data ON (data.mimetype_id=? AND "
134e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "data.raw_contact_id = raw_contacts._id) "
135e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN groups ON (groups._id = data." + GroupMembership.GROUP_ROW_ID
136e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + ")";
137e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
138e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        // NOTE: This requires late binding of GroupMembership MIME-type
139e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS = "settings "
140e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN raw_contacts ON ("
141e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_name = settings.account_name AND "
142e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_type = settings.account_type) "
143e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN data ON (data.mimetype_id=? AND "
144e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "data.raw_contact_id = raw_contacts._id) "
145e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
146e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
147d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS = "data "
1481b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
1491b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) "
150d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
151ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
1525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_GROUPS = "data "
1531b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
1541b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) "
15567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                + "LEFT OUTER JOIN packages ON (data.package_id = packages._id) "
1569261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "LEFT OUTER JOIN groups "
1579261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "  ON (mimetypes.mimetype='" + GroupMembership.CONTENT_ITEM_TYPE + "' "
1589261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "      AND groups._id = data." + GroupMembership.GROUP_ROW_ID + ") ";
159ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
160ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String GROUPS_JOIN_PACKAGES = "groups "
161ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN packages ON (groups.package_id = packages._id)";
162ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
163b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
164b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String ACTIVITIES = "activities";
165b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
166ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String ACTIVITIES_JOIN_MIMETYPES = "activities "
167ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (activities.mimetype_id = mimetypes._id)";
168b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
169d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String ACTIVITIES_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS =
1705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                "activities "
17167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                + "LEFT OUTER JOIN packages ON (activities.package_id = packages._id) "
172ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (activities.mimetype_id = mimetypes._id) "
1735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "LEFT OUTER JOIN raw_contacts ON (activities.author_contact_id = " +
174fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        "raw_contacts._id) "
175d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
1767e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana
1775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String NAME_LOOKUP_JOIN_RAW_CONTACTS = "name_lookup "
1785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "INNER JOIN raw_contacts ON (name_lookup.raw_contact_id = raw_contacts._id)";
179b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
180b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public interface Views {
1824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String DATA_ALL = "view_data";
1834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String DATA_RESTRICTED = "view_data_restricted";
1844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
1854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String RAW_CONTACTS_ALL = "view_raw_contacts";
1864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String RAW_CONTACTS_RESTRICTED = "view_raw_contacts_restricted";
1874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
1884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String CONTACTS_ALL = "view_contacts";
1894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String CONTACTS_RESTRICTED = "view_contacts_restricted";
19089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
191a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        public static final String ENTITIES = "view_entities";
192a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        public static final String ENTITIES_RESTRICTED = "view_entities_restricted";
193a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
194a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        public static final String RAW_ENTITIES = "view_raw_entities";
195a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        public static final String RAW_ENTITIES_RESTRICTED = "view_raw_entities_restricted";
196a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
19789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        public static final String GROUPS_ALL = "view_groups";
1984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
1994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
2001f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    public interface Clauses {
201e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String MIMETYPE_IS_GROUP_MEMBERSHIP = MimetypesColumns.CONCRETE_MIMETYPE + "='"
202e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + GroupMembership.CONTENT_ITEM_TYPE + "'";
203ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
204e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String BELONGS_TO_GROUP = DataColumns.CONCRETE_GROUP_ID + "="
205ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + GroupsColumns.CONCRETE_ID;
206ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
20768936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey        final String HAVING_NO_GROUPS = "COUNT(" + DataColumns.CONCRETE_GROUP_ID + ") == 0";
2089261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana
20968936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey        final String GROUP_BY_ACCOUNT_CONTACT_ID = SettingsColumns.CONCRETE_ACCOUNT_NAME + ","
21068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey                + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "," + RawContacts.CONTACT_ID;
211e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
212e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String RAW_CONTACT_IS_LOCAL = RawContactsColumns.CONCRETE_ACCOUNT_NAME
213e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + " IS NULL AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL";
214e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
215e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String ZERO_GROUP_MEMBERSHIPS = "COUNT(" + GroupsColumns.CONCRETE_ID + ")=0";
216e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
2171a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey        final String OUTER_RAW_CONTACTS = "outer_raw_contacts";
2181a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey        final String OUTER_RAW_CONTACTS_ID = OUTER_RAW_CONTACTS + "." + RawContacts._ID;
2191a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey
220b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov        final String CONTACT_IS_VISIBLE =
221b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                "SELECT " +
2221a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey                    "MAX((SELECT (CASE WHEN " +
223b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                        "(CASE" +
224b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " WHEN " + RAW_CONTACT_IS_LOCAL +
225b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " THEN 1 " +
226b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " WHEN " + ZERO_GROUP_MEMBERSHIPS +
227b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " THEN " + Settings.UNGROUPED_VISIBLE +
228b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " ELSE MAX(" + Groups.GROUP_VISIBLE + ")" +
229b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                         "END)=1 THEN 1 ELSE 0 END)" +
230b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS_JOIN_SETTINGS_DATA_GROUPS +
2311a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey                " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + OUTER_RAW_CONTACTS_ID + "))" +
2321a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey                " FROM " + Tables.RAW_CONTACTS + " AS " + OUTER_RAW_CONTACTS +
233b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
234b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                " GROUP BY " + RawContacts.CONTACT_ID;
235e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
236e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String GROUP_HAS_ACCOUNT_AND_SOURCE_ID = Groups.SOURCE_ID + "=? AND "
237e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + Groups.ACCOUNT_NAME + "=? AND " + Groups.ACCOUNT_TYPE + "=?";
2384394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
2394394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        public static final String CONTACT_VISIBLE =
2404394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            "EXISTS (SELECT _id FROM " + Tables.VISIBLE_CONTACTS
2414394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                + " WHERE " + Tables.CONTACTS +"." + Contacts._ID
2424394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        + "=" + Tables.VISIBLE_CONTACTS +"." + Contacts._ID + ")";
2431f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    }
2441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
245d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    public interface ContactsColumns {
2464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        /**
2474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov         * This flag is set for a contact if it has only one constituent raw contact and
2484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov         * it is restricted.
2494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov         */
25067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String SINGLE_IS_RESTRICTED = "single_is_restricted";
251ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
252a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        public static final String LAST_STATUS_UPDATE_ID = "status_update_id";
253a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov
254d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_ID = Tables.CONTACTS + "." + BaseColumns._ID;
25567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
256d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_TIMES_CONTACTED = Tables.CONTACTS + "."
257d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.TIMES_CONTACTED;
258d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_LAST_TIME_CONTACTED = Tables.CONTACTS + "."
259d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.LAST_TIME_CONTACTED;
260d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_STARRED = Tables.CONTACTS + "." + Contacts.STARRED;
261d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_CUSTOM_RINGTONE = Tables.CONTACTS + "."
262d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.CUSTOM_RINGTONE;
263d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_SEND_TO_VOICEMAIL = Tables.CONTACTS + "."
264d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.SEND_TO_VOICEMAIL;
2652d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill        public static final String CONCRETE_LOOKUP_KEY = Tables.CONTACTS + "."
2662d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill                + Contacts.LOOKUP_KEY;
267619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
268619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
2696cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov    public interface RawContactsColumns {
27033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_ID =
2715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + BaseColumns._ID;
2729261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana        public static final String CONCRETE_ACCOUNT_NAME =
2735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.ACCOUNT_NAME;
2749261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana        public static final String CONCRETE_ACCOUNT_TYPE =
2755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.ACCOUNT_TYPE;
27633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_SOURCE_ID =
2775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.SOURCE_ID;
27833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_VERSION =
2795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.VERSION;
28033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_DIRTY =
2815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.DIRTY;
28233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_DELETED =
2835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.DELETED;
2847a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC1 =
2857a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC1;
2867a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC2 =
2877a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC2;
2887a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC3 =
2897a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC3;
2907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC4 =
2917a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC4;
292c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey        public static final String CONCRETE_STARRED =
293c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey                Tables.RAW_CONTACTS + "." + RawContacts.STARRED;
294bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey        public static final String CONCRETE_IS_RESTRICTED =
295bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey                Tables.RAW_CONTACTS + "." + RawContacts.IS_RESTRICTED;
2968e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov
2975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        public static final String DISPLAY_NAME = RawContacts.DISPLAY_NAME_PRIMARY;
2985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        public static final String DISPLAY_NAME_SOURCE = RawContacts.DISPLAY_NAME_SOURCE;
2998e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov        public static final String AGGREGATION_NEEDED = "aggregation_needed";
300fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
301fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        public static final String CONCRETE_DISPLAY_NAME =
302fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Tables.RAW_CONTACTS + "." + DISPLAY_NAME;
303fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        public static final String CONCRETE_CONTACT_ID =
304fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.CONTACT_ID;
305f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        public static final String CONCRETE_NAME_VERIFIED =
306f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.NAME_VERIFIED;
307619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
308619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
309619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    public interface DataColumns {
31067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String PACKAGE_ID = "package_id";
311b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE_ID = "mimetype_id";
312ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
313ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.DATA + "." + BaseColumns._ID;
314226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_MIMETYPE_ID = Tables.DATA + "." + MIMETYPE_ID;
315d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_RAW_CONTACT_ID = Tables.DATA + "."
316d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Data.RAW_CONTACT_ID;
317ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_GROUP_ID = Tables.DATA + "."
318ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + GroupMembership.GROUP_ROW_ID;
319e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov
320e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA1 = Tables.DATA + "." + Data.DATA1;
321e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA2 = Tables.DATA + "." + Data.DATA2;
322e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA3 = Tables.DATA + "." + Data.DATA3;
323e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA4 = Tables.DATA + "." + Data.DATA4;
324e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA5 = Tables.DATA + "." + Data.DATA5;
325e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA6 = Tables.DATA + "." + Data.DATA6;
326e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA7 = Tables.DATA + "." + Data.DATA7;
327e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA8 = Tables.DATA + "." + Data.DATA8;
328e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA9 = Tables.DATA + "." + Data.DATA9;
329e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA10 = Tables.DATA + "." + Data.DATA10;
3300f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA11 = Tables.DATA + "." + Data.DATA11;
3310f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA12 = Tables.DATA + "." + Data.DATA12;
3320f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA13 = Tables.DATA + "." + Data.DATA13;
3330f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA14 = Tables.DATA + "." + Data.DATA14;
3340f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA15 = Tables.DATA + "." + Data.DATA15;
335e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_IS_PRIMARY = Tables.DATA + "." + Data.IS_PRIMARY;
336226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_PACKAGE_ID = Tables.DATA + "." + PACKAGE_ID;
337e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov    }
338e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov
3390f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    // Used only for legacy API support
3400f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    public interface ExtensionsColumns {
3410f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String NAME = Data.DATA1;
3420f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String VALUE = Data.DATA2;
3430f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    }
3440f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov
3450f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    public interface GroupMembershipColumns {
3465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = Data.RAW_CONTACT_ID;
3470f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String GROUP_ROW_ID = GroupMembership.GROUP_ROW_ID;
3480f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    }
3490f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov
350e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov    public interface PhoneColumns {
351e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String NORMALIZED_NUMBER = Data.DATA4;
352e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_NORMALIZED_NUMBER = DataColumns.CONCRETE_DATA4;
353ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
354ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
355ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface GroupsColumns {
35667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String PACKAGE_ID = "package_id";
35767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
358ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.GROUPS + "." + BaseColumns._ID;
35967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String CONCRETE_SOURCE_ID = Tables.GROUPS + "." + Groups.SOURCE_ID;
360341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey        public static final String CONCRETE_ACCOUNT_NAME = Tables.GROUPS + "." + Groups.ACCOUNT_NAME;
361341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey        public static final String CONCRETE_ACCOUNT_TYPE = Tables.GROUPS + "." + Groups.ACCOUNT_TYPE;
362341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey    }
363b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
364b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface ActivitiesColumns {
365b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PACKAGE_ID = "package_id";
366b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE_ID = "mimetype_id";
367b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
368b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
369b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface PhoneLookupColumns {
370b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
371b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA_ID = "data_id";
3725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = "raw_contact_id";
373b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String NORMALIZED_NUMBER = "normalized_number";
37436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        public static final String MIN_MATCH = "min_match";
375b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
376b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
377a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    public interface NameLookupColumns {
3785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = "raw_contact_id";
37914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        public static final String DATA_ID = "data_id";
380a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NORMALIZED_NAME = "normalized_name";
381a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NAME_TYPE = "name_type";
382a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
383a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
384a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov    public final static class NameLookupType {
3852a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NAME_EXACT = 0;
3862a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NAME_VARIANT = 1;
3872a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NAME_COLLATION_KEY = 2;
3882a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NICKNAME = 3;
3892a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int EMAIL_BASED_NICKNAME = 4;
390a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka        public static final int ORGANIZATION = 5;
3914cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao        public static final int NAME_SHORTHAND = 6;
392f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        public static final int NAME_CONSONANTS = 7;
393a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
394a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        // This is the highest name lookup type code plus one
3955086b63bf3de5f26f495b640e85259c0ebf5ca47Dmitri Plotnikov        public static final int TYPE_COUNT = 8;
396a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov
397a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        public static boolean isBasedOnStructuredName(int nameLookupType) {
3982a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov            return nameLookupType == NameLookupType.NAME_EXACT
3992a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov                    || nameLookupType == NameLookupType.NAME_VARIANT
4002a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov                    || nameLookupType == NameLookupType.NAME_COLLATION_KEY;
401a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        }
402a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
403a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
404ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface PackagesColumns {
405b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
406b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PACKAGE = "package";
407226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana
408226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_ID = Tables.PACKAGES + "." + _ID;
409b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
410b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
411ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface MimetypesColumns {
412b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
413b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE = "mimetype";
414ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
415ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.MIMETYPES + "." + BaseColumns._ID;
416ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_MIMETYPE = Tables.MIMETYPES + "." + MIMETYPE;
417b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
418b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
419b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov    public interface AggregationExceptionColumns {
420b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        public static final String _ID = BaseColumns._ID;
421b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov    }
422b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
423b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    public interface NicknameLookupColumns {
424b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String NAME = "name";
425b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String CLUSTER = "cluster";
426b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    }
427b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
428e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey    public interface SettingsColumns {
429e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String CONCRETE_ACCOUNT_NAME = Tables.SETTINGS + "."
430e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + Settings.ACCOUNT_NAME;
431e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String CONCRETE_ACCOUNT_TYPE = Tables.SETTINGS + "."
432e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + Settings.ACCOUNT_TYPE;
433e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey    }
434e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
4354dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov    public interface PresenceColumns {
4364dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov        String RAW_CONTACT_ID = "presence_raw_contact_id";
437bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        String CONTACT_ID = "presence_contact_id";
4384dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov    }
4394dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov
440e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov    public interface AggregatedPresenceColumns {
441e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        String CONTACT_ID = "presence_contact_id";
4423296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4433296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_CONTACT_ID = Tables.AGGREGATED_PRESENCE + "." + CONTACT_ID;
444e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov    }
445e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov
446a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov    public interface StatusUpdatesColumns {
447a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        String DATA_ID = "status_update_data_id";
4483296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4493296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_DATA_ID = Tables.STATUS_UPDATES + "." + DATA_ID;
4503296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4513296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_PRESENCE = Tables.STATUS_UPDATES + "." + StatusUpdates.PRESENCE;
4523296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS = Tables.STATUS_UPDATES + "." + StatusUpdates.STATUS;
4533296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_TIMESTAMP = Tables.STATUS_UPDATES + "."
4543296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey                + StatusUpdates.STATUS_TIMESTAMP;
4553296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_RES_PACKAGE = Tables.STATUS_UPDATES + "."
4563296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey                + StatusUpdates.STATUS_RES_PACKAGE;
4573296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_LABEL = Tables.STATUS_UPDATES + "." + StatusUpdates.STATUS_LABEL;
4583296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_ICON = Tables.STATUS_UPDATES + "." + StatusUpdates.STATUS_ICON;
4593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey    }
4603296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey    public interface ContactsStatusUpdatesColumns {
4623296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String ALIAS = "contacts_" + Tables.STATUS_UPDATES;
4633296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4643296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_DATA_ID = ALIAS + "." + StatusUpdatesColumns.DATA_ID;
4653296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4663296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_PRESENCE = ALIAS + "." + StatusUpdates.PRESENCE;
4673296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS = ALIAS + "." + StatusUpdates.STATUS;
4683296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_TIMESTAMP = ALIAS + "." + StatusUpdates.STATUS_TIMESTAMP;
4693296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_RES_PACKAGE = ALIAS + "." + StatusUpdates.STATUS_RES_PACKAGE;
4703296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_LABEL = ALIAS + "." + StatusUpdates.STATUS_LABEL;
4713296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_ICON = ALIAS + "." + StatusUpdates.STATUS_ICON;
472a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov    }
473a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov
474b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public interface PropertiesColumns {
475b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        String PROPERTY_KEY = "property_key";
476b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        String PROPERTY_VALUE = "property_value";
477b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
478b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
4793296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey    /** In-memory cache of previously found MIME-type mappings */
480bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    private final HashMap<String, Long> mMimetypeCache = new HashMap<String, Long>();
481b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** In-memory cache of previously found package name mappings */
482bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    private final HashMap<String, Long> mPackageCache = new HashMap<String, Long>();
483b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
484b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
485b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** Compiled statements for querying and inserting mappings */
486b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mMimetypeQuery;
487b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mPackageQuery;
488d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    private SQLiteStatement mContactIdQuery;
489f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    private SQLiteStatement mAggregationModeQuery;
490b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mMimetypeInsert;
491b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mPackageInsert;
492b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mDataMimetypeQuery;
493b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mActivitiesMimetypeQuery;
494b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
495b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private final Context mContext;
49635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    private final SyncStateContentProviderHelper mSyncState;
497f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov
498f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    private boolean mReopenDatabase = false;
499f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
500b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    private static ContactsDatabaseHelper sSingleton = null;
501b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
50236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    private boolean mUseStrictPhoneNumberComparison;
5033a6a49cfb06272e3e25f3c390a9cf4002da6e34dDaisuke Miyakawa
504d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    /**
505d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton     * List of package names with access to {@link RawContacts#IS_RESTRICTED} data.
506d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton     */
507d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    private String[] mUnrestrictedPackages;
508d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton
509b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    public static synchronized ContactsDatabaseHelper getInstance(Context context) {
510b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (sSingleton == null) {
511b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov            sSingleton = new ContactsDatabaseHelper(context);
512b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
513b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return sSingleton;
514b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
515b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
5161f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    /**
51731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov     * Private constructor, callers except unit tests should obtain an instance through
51835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana     * {@link #getInstance(android.content.Context)} instead.
5191f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey     */
520b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    ContactsDatabaseHelper(Context context) {
521b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        super(context, DATABASE_NAME, null, DATABASE_VERSION);
522d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        Resources resources = context.getResources();
523619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
524b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        mContext = context;
52528b3769e3fcecae56c3fc70cbcb0f95282b9640eFred Quintana        mSyncState = new SyncStateContentProviderHelper();
52636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        mUseStrictPhoneNumberComparison =
527d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                resources.getBoolean(
528d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                        com.android.internal.R.bool.config_use_strict_phone_number_comparation);
5290f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        int resourceId = resources.getIdentifier("unrestricted_packages", "array",
5300f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov                context.getPackageName());
5310f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        if (resourceId != 0) {
5320f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov            mUnrestrictedPackages = resources.getStringArray(resourceId);
5330f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        } else {
5340f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov            mUnrestrictedPackages = new String[0];
5350f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        }
536b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
537b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
538b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
539b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onOpen(SQLiteDatabase db) {
54035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        mSyncState.onDatabaseOpened(db);
54135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
542b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Create compiled statements for package and mimetype lookups
543ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mMimetypeQuery = db.compileStatement("SELECT " + MimetypesColumns._ID + " FROM "
544ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + Tables.MIMETYPES + " WHERE " + MimetypesColumns.MIMETYPE + "=?");
545ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mPackageQuery = db.compileStatement("SELECT " + PackagesColumns._ID + " FROM "
546ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + Tables.PACKAGES + " WHERE " + PackagesColumns.PACKAGE + "=?");
547d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        mContactIdQuery = db.compileStatement("SELECT " + RawContacts.CONTACT_ID + " FROM "
5485ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?");
5496cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov        mAggregationModeQuery = db.compileStatement("SELECT " + RawContacts.AGGREGATION_MODE
5505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?");
551ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mMimetypeInsert = db.compileStatement("INSERT INTO " + Tables.MIMETYPES + "("
552ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + MimetypesColumns.MIMETYPE + ") VALUES (?)");
553ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mPackageInsert = db.compileStatement("INSERT INTO " + Tables.PACKAGES + "("
554ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + PackagesColumns.PACKAGE + ") VALUES (?)");
555ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
556ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mDataMimetypeQuery = db.compileStatement("SELECT " + MimetypesColumns.MIMETYPE + " FROM "
557ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + Tables.DATA_JOIN_MIMETYPES + " WHERE " + Tables.DATA + "." + Data._ID + "=?");
558ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mActivitiesMimetypeQuery = db.compileStatement("SELECT " + MimetypesColumns.MIMETYPE
559ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + " FROM " + Tables.ACTIVITIES_JOIN_MIMETYPES + " WHERE " + Tables.ACTIVITIES + "."
560b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + Activities._ID + "=?");
5611f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
5621f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        db.execSQL("ATTACH DATABASE ':memory:' AS " + DATABASE_PRESENCE + ";");
563e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS " + DATABASE_PRESENCE + "." + Tables.PRESENCE + " ("+
56482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.DATA_ID + " INTEGER PRIMARY KEY REFERENCES data(_id)," +
56582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.PROTOCOL + " INTEGER NOT NULL," +
56682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.CUSTOM_PROTOCOL + " TEXT," +
56782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.IM_HANDLE + " TEXT," +
56882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.IM_ACCOUNT + " TEXT," +
569a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                PresenceColumns.CONTACT_ID + " INTEGER REFERENCES contacts(_id)," +
570a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                PresenceColumns.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
57182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.PRESENCE + " INTEGER," +
572aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                StatusUpdates.CHAT_CAPABILITY + " INTEGER NOT NULL DEFAULT 0," +
57382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                "UNIQUE(" + StatusUpdates.PROTOCOL + ", " + StatusUpdates.CUSTOM_PROTOCOL
57482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                    + ", " + StatusUpdates.IM_HANDLE + ", " + StatusUpdates.IM_ACCOUNT + ")" +
5751f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        ");");
5761f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
577e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE INDEX IF NOT EXISTS " + DATABASE_PRESENCE + ".presenceIndex" + " ON "
5784dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov                + Tables.PRESENCE + " (" + PresenceColumns.RAW_CONTACT_ID + ");");
579e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov
580e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS "
581aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + DATABASE_PRESENCE + "." + Tables.AGGREGATED_PRESENCE + " ("+
582e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov                AggregatedPresenceColumns.CONTACT_ID
583e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov                        + " INTEGER PRIMARY KEY REFERENCES contacts(_id)," +
584632248ae0053fa99b1f5b4cfaab3e55b7453fcb1Vasu Nori                StatusUpdates.PRESENCE + " INTEGER," +
585aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                StatusUpdates.CHAT_CAPABILITY + " INTEGER NOT NULL DEFAULT 0" +
586e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        ");");
587bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
588bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
589bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_deleted"
590bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEFORE DELETE ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
591bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
592bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + "   DELETE FROM " + Tables.AGGREGATED_PRESENCE
593bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + "     WHERE " + AggregatedPresenceColumns.CONTACT_ID + " = " +
594bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        "(SELECT " + PresenceColumns.CONTACT_ID +
595bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " FROM " + Tables.PRESENCE +
596bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " WHERE " + PresenceColumns.RAW_CONTACT_ID
597bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                + "=OLD." + PresenceColumns.RAW_CONTACT_ID +
598bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " AND NOT EXISTS" +
599bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                "(SELECT " + PresenceColumns.RAW_CONTACT_ID +
600bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " FROM " + Tables.PRESENCE +
601bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " WHERE " + PresenceColumns.CONTACT_ID
602bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                        + "=OLD." + PresenceColumns.CONTACT_ID +
603bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " AND " + PresenceColumns.RAW_CONTACT_ID
604bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                        + "!=OLD." + PresenceColumns.RAW_CONTACT_ID + "));"
605bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
606bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
607aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori        final String replaceAggregatePresenceSql =
608aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                "INSERT OR REPLACE INTO " + Tables.AGGREGATED_PRESENCE + "("
609aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + AggregatedPresenceColumns.CONTACT_ID + ", "
610a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + StatusUpdates.PRESENCE + ", "
611aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + StatusUpdates.CHAT_CAPABILITY + ")"
612aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " SELECT " + PresenceColumns.CONTACT_ID + ","
613a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + StatusUpdates.PRESENCE + ","
614aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + StatusUpdates.CHAT_CAPABILITY
615aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " FROM " + Tables.PRESENCE
616aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " WHERE "
617a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " (" + StatusUpdates.PRESENCE
618aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                +       " * 10 + " + StatusUpdates.CHAT_CAPABILITY + ")"
619aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " = (SELECT "
620a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + "MAX (" + StatusUpdates.PRESENCE
621aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                +       " * 10 + " + StatusUpdates.CHAT_CAPABILITY + ")"
622aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " FROM " + Tables.PRESENCE
623aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " WHERE " + PresenceColumns.CONTACT_ID
624aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + "=NEW." + PresenceColumns.CONTACT_ID + ")"
625aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " AND " + PresenceColumns.CONTACT_ID
626aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + "=NEW." + PresenceColumns.CONTACT_ID + ";";
627bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
628bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_inserted"
629bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " AFTER INSERT ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
630bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
631bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + replaceAggregatePresenceSql
632bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
633bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
634bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_updated"
635bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " AFTER UPDATE ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
636bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
637bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + replaceAggregatePresenceSql
638bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
639b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
640b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
641b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
642b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onCreate(SQLiteDatabase db) {
643b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        Log.i(TAG, "Bootstrapping database");
644b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
64535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        mSyncState.createDatabase(db);
64635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
647b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // One row per group of contacts corresponding to the same person
648d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.CONTACTS + " (" +
649b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
650fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
651d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.PHOTO_ID + " INTEGER REFERENCES data(_id)," +
652d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.CUSTOM_RINGTONE + " TEXT," +
653d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," +
654d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," +
655d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.LAST_TIME_CONTACTED + " INTEGER," +
656d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.STARRED + " INTEGER NOT NULL DEFAULT 0," +
657f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov                Contacts.HAS_PHONE_NUMBER + " INTEGER NOT NULL DEFAULT 0," +
6585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                Contacts.LOOKUP_KEY + " TEXT," +
659a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                ContactsColumns.LAST_STATUS_UPDATE_ID + " INTEGER REFERENCES data(_id)," +
6604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.SINGLE_IS_RESTRICTED + " INTEGER NOT NULL DEFAULT 0" +
661b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
662b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
66354d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX contacts_has_phone_index ON " + Tables.CONTACTS + " (" +
66454d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                Contacts.HAS_PHONE_NUMBER +
66554d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
66654d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
66754d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX contacts_restricted_index ON " + Tables.CONTACTS + " (" +
66854d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                ContactsColumns.SINGLE_IS_RESTRICTED +
66954d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
67054d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
671fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_name_raw_contact_id_index ON " + Tables.CONTACTS + " (" +
672fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID +
673fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
674fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
675b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Contacts table
6765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.RAW_CONTACTS + " (" +
6776cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
6786cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.IS_RESTRICTED + " INTEGER DEFAULT 0," +
6796cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.ACCOUNT_NAME + " STRING DEFAULT NULL, " +
6806cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + " STRING DEFAULT NULL, " +
6816cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.SOURCE_ID + " TEXT," +
68297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                RawContacts.RAW_CONTACT_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
6836cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.VERSION + " INTEGER NOT NULL DEFAULT 1," +
68473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov                RawContacts.DIRTY + " INTEGER NOT NULL DEFAULT 0," +
68533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov                RawContacts.DELETED + " INTEGER NOT NULL DEFAULT 0," +
68654d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                RawContacts.CONTACT_ID + " INTEGER REFERENCES contacts(_id)," +
6876cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.AGGREGATION_MODE + " INTEGER NOT NULL DEFAULT " +
6886cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                        RawContacts.AGGREGATION_MODE_DEFAULT + "," +
6898e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov                RawContactsColumns.AGGREGATION_NEEDED + " INTEGER NOT NULL DEFAULT 1," +
6906cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.CUSTOM_RINGTONE + " TEXT," +
6916cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," +
6926cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," +
6936cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.LAST_TIME_CONTACTED + " INTEGER," +
69433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov                RawContacts.STARRED + " INTEGER NOT NULL DEFAULT 0," +
6955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_PRIMARY + " TEXT," +
6965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_ALTERNATIVE + " TEXT," +
6975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_SOURCE + " INTEGER NOT NULL DEFAULT " +
69825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov                        DisplayNameSources.UNDEFINED + "," +
6995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.PHONETIC_NAME + " TEXT," +
7005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.PHONETIC_NAME_STYLE + " TEXT," +
701de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                RawContacts.SORT_KEY_PRIMARY + " TEXT COLLATE " +
702de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                        ContactsProvider2.PHONEBOOK_COLLATOR_NAME + "," +
703de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                RawContacts.SORT_KEY_ALTERNATIVE + " TEXT COLLATE " +
704de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                        ContactsProvider2.PHONEBOOK_COLLATOR_NAME + "," +
705f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                RawContacts.NAME_VERIFIED + " INTEGER NOT NULL DEFAULT 0," +
7063cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC1 + " TEXT, " +
7073cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC2 + " TEXT, " +
7083cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC3 + " TEXT, " +
7093cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC4 + " TEXT " +
710b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
711b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
71254d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contacts_contact_id_index ON " + Tables.RAW_CONTACTS + " (" +
71354d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                RawContacts.CONTACT_ID +
71454d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
71554d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
7165f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contacts_source_id_index ON " + Tables.RAW_CONTACTS + " (" +
7175f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.SOURCE_ID + ", " +
7185f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + ", " +
7195f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.ACCOUNT_NAME +
7205f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        ");");
7215f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov
722f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        // TODO readd the index and investigate a controlled use of it
723f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//        db.execSQL("CREATE INDEX raw_contacts_agg_index ON " + Tables.RAW_CONTACTS + " (" +
724f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//                RawContactsColumns.AGGREGATION_NEEDED +
725f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//        ");");
7268e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov
727b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Package name mapping table
728ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PACKAGES + " (" +
729ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                PackagesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
730ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                PackagesColumns.PACKAGE + " TEXT NOT NULL" +
731b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
732b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
733ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // Mimetype mapping table
734ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.MIMETYPES + " (" +
735ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                MimetypesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
736ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                MimetypesColumns.MIMETYPE + " TEXT NOT NULL" +
737b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
738b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
73908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        // Mimetype table requires an index on mime type
74008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX mime_type ON " + Tables.MIMETYPES + " (" +
74108768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov                MimetypesColumns.MIMETYPE +
74208768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        ");");
74308768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
744b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Public generic data table
745b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.DATA + " (" +
746b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
74767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                DataColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
748b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                DataColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
74911944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                Data.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
75097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                Data.IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
751f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.IS_PRIMARY + " INTEGER NOT NULL DEFAULT 0," +
752f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.IS_SUPER_PRIMARY + " INTEGER NOT NULL DEFAULT 0," +
753f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA_VERSION + " INTEGER NOT NULL DEFAULT 0," +
754f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA1 + " TEXT," +
755f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA2 + " TEXT," +
756f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA3 + " TEXT," +
757f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA4 + " TEXT," +
758f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA5 + " TEXT," +
759f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA6 + " TEXT," +
760f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA7 + " TEXT," +
761f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA8 + " TEXT," +
762f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA9 + " TEXT," +
76367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA10 + " TEXT," +
76467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA11 + " TEXT," +
76567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA12 + " TEXT," +
76667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA13 + " TEXT," +
76767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA14 + " TEXT," +
7683cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.DATA15 + " TEXT," +
7693cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC1 + " TEXT, " +
7703cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC2 + " TEXT, " +
7713cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC3 + " TEXT, " +
7723cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC4 + " TEXT " +
773b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
774b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
77511944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        db.execSQL("CREATE INDEX data_raw_contact_id ON " + Tables.DATA + " (" +
77611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                Data.RAW_CONTACT_ID +
77711944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        ");");
77811944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
77911944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        /**
78011944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov         * For email lookup and similar queries.
78111944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov         */
782f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov        db.execSQL("CREATE INDEX data_mimetype_data1_index ON " + Tables.DATA + " (" +
78311944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "," +
784f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov                Data.DATA1 +
78511944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        ");");
78611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
787b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Private phone numbers table used for lookup
788b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" +
789f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.DATA_ID
790892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        + " INTEGER REFERENCES data(_id) NOT NULL," +
7915ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID
7925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
79336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL," +
79436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL" +
795b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
796b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
797b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" +
798f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + "," +
799f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
800b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.DATA_ID +
801b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
802b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
80336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
80436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
80536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
80636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
80736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        ");");
80836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
809a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        // Private name/nickname table used for lookup
810a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.NAME_LOOKUP + " (" +
81114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                NameLookupColumns.DATA_ID
81214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                        + " INTEGER REFERENCES data(_id) NOT NULL," +
8135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID
8145ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
81511944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                NameLookupColumns.NORMALIZED_NAME + " TEXT NOT NULL," +
81611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                NameLookupColumns.NAME_TYPE + " INTEGER NOT NULL," +
81714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                "PRIMARY KEY ("
81814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                        + NameLookupColumns.DATA_ID + ", "
81911944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                        + NameLookupColumns.NORMALIZED_NAME + ", "
82011944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                        + NameLookupColumns.NAME_TYPE + ")" +
821a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        ");");
822a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
82314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        db.execSQL("CREATE INDEX name_lookup_raw_contact_id_index ON " + Tables.NAME_LOOKUP + " (" +
82414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID +
82514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        ");");
82614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov
827b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.NICKNAME_LOOKUP + " (" +
828b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + " TEXT," +
829b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.CLUSTER + " TEXT" +
830b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        ");");
831b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
832b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX nickname_lookup_index ON " + Tables.NICKNAME_LOOKUP + " (" +
833b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + ", " +
834b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.CLUSTER +
835b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        ");");
836b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
837ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // Groups table
838ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.GROUPS + " (" +
839ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
84067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                GroupsColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
841035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana                Groups.ACCOUNT_NAME + " STRING DEFAULT NULL, " +
842035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana                Groups.ACCOUNT_TYPE + " STRING DEFAULT NULL, " +
843ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups.SOURCE_ID + " TEXT," +
8449261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                Groups.VERSION + " INTEGER NOT NULL DEFAULT 1," +
84573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov                Groups.DIRTY + " INTEGER NOT NULL DEFAULT 0," +
846ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups.TITLE + " TEXT," +
84767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Groups.TITLE_RES + " INTEGER," +
8480f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov                Groups.NOTES + " TEXT," +
8490f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov                Groups.SYSTEM_ID + " TEXT," +
85094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana                Groups.DELETED + " INTEGER NOT NULL DEFAULT 0," +
851eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Groups.GROUP_VISIBLE + " INTEGER NOT NULL DEFAULT 0," +
852ea547d55f864133861b2db44221ae0c2ac6c1a68Fred Quintana                Groups.SHOULD_SYNC + " INTEGER NOT NULL DEFAULT 1," +
853dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                Groups.AUTO_ADD + " INTEGER NOT NULL DEFAULT 0," +
854dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                Groups.FAVORITES + " INTEGER NOT NULL DEFAULT 0," +
8553cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC1 + " TEXT, " +
8563cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC2 + " TEXT, " +
8573cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC3 + " TEXT, " +
8583cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC4 + " TEXT " +
859ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        ");");
860ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
8615f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        db.execSQL("CREATE INDEX groups_source_id_index ON " + Tables.GROUPS + " (" +
8625f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.SOURCE_ID + ", " +
8635f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.ACCOUNT_TYPE + ", " +
8645f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.ACCOUNT_NAME +
8655f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        ");");
8665f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov
867b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.AGGREGATION_EXCEPTIONS + " (" +
868b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                AggregationExceptionColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
869b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                AggregationExceptions.TYPE + " INTEGER NOT NULL, " +
8700c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1
8715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id), " +
8720c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2
8735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id)" +
874b0160a0bcf6d59eaa43fd501e124b95f873e0157Marc Blank        ");");
875b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
876b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index1 ON " +
877b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                Tables.AGGREGATION_EXCEPTIONS + " (" +
8780c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1 + ", " +
8790c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2 +
880b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        ");");
881b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
882b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index2 ON " +
883b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                Tables.AGGREGATION_EXCEPTIONS + " (" +
8840c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2 + ", " +
8850c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1 +
886b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        ");");
887b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
888eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.SETTINGS + " (" +
889eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.ACCOUNT_NAME + " STRING NOT NULL," +
890eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.ACCOUNT_TYPE + " STRING NOT NULL," +
891eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.UNGROUPED_VISIBLE + " INTEGER NOT NULL DEFAULT 0," +
892eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.SHOULD_SYNC + " INTEGER NOT NULL DEFAULT 1, " +
893eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                "PRIMARY KEY (" + Settings.ACCOUNT_NAME + ", " +
894e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    Settings.ACCOUNT_TYPE + ") ON CONFLICT REPLACE" +
895eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        ");");
896eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey
8974394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.VISIBLE_CONTACTS + " (" +
8984394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
8994394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
9004394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
901385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DEFAULT_DIRECTORY + " (" +
902385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
903385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        ");");
904385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
905e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        // The table for recent calls is here so we can do table joins
906e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        // on people, phones, and calls all in one place.
907e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.CALLS + " (" +
908e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
909e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.NUMBER + " TEXT," +
910e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.DATE + " INTEGER," +
911e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.DURATION + " INTEGER," +
912e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.TYPE + " INTEGER," +
913e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.NEW + " INTEGER," +
914e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NAME + " TEXT," +
915e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NUMBER_TYPE + " INTEGER," +
9162530512f639c4979fd7371c7dd25dd67e8118124Bai Tao                Calls.CACHED_NUMBER_LABEL + " TEXT," +
9172530512f639c4979fd7371c7dd25dd67e8118124Bai Tao                Calls.COUNTRY_ISO + " TEXT" + ");");
918e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov
919b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Activities table
920b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.ACTIVITIES + " (" +
921b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
92267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                ActivitiesColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
923b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                ActivitiesColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
924b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.RAW_ID + " TEXT," +
925499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.IN_REPLY_TO + " TEXT," +
9265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Activities.AUTHOR_CONTACT_ID +  " INTEGER REFERENCES raw_contacts(_id)," +
9275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Activities.TARGET_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
928b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.PUBLISHED + " INTEGER NOT NULL," +
929499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.THREAD_PUBLISHED + " INTEGER NOT NULL," +
930b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.TITLE + " TEXT NOT NULL," +
931b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.SUMMARY + " TEXT," +
932adb55c2d8295d300961d86a3605c8ddc469cd4a2Dmitri Plotnikov                Activities.LINK + " TEXT, " +
933b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.THUMBNAIL + " BLOB" +
934b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
935b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
936a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.STATUS_UPDATES + " (" +
937a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                StatusUpdatesColumns.DATA_ID + " INTEGER PRIMARY KEY REFERENCES data(_id)," +
9380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS + " TEXT," +
9390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_TIMESTAMP + " INTEGER," +
9400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_RES_PACKAGE + " TEXT, " +
9410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_LABEL + " INTEGER, " +
9420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_ICON + " INTEGER" +
943a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        ");");
944a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov
945b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.PROPERTIES + " (" +
946b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_KEY + " TEXT PRIMARY KEY, " +
947b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_VALUE + " TEXT " +
948b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ");");
949b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
950743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.ACCOUNTS + " (" +
951743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov                RawContacts.ACCOUNT_NAME + " TEXT, " +
952743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + " TEXT " +
953743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        ");");
954743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
955743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // Allow contacts without any account to be created for now.  Achieve that
956743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // by inserting a fake account with both type and name as NULL.
957743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // This "account" should be eliminated as soon as the first real writable account
958743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // is added to the phone.
959743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        db.execSQL("INSERT INTO accounts VALUES(NULL, NULL)");
960743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
961d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        createDirectoriesTable(db);
962d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
963a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        createContactsViews(db);
964a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        createGroupsView(db);
965fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        createContactsTriggers(db);
966916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        createContactsIndexes(db);
9674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
968a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        loadNicknameLookupTable(db);
969a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
970a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        // Add the legacy API support views, etc
971a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        LegacyApiSupport.createDatabase(db);
972a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
973a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        // This will create a sqlite_stat1 table that is used for query optimization
974a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("ANALYZE;");
975a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
976a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        updateSqliteStats(db);
977a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
978a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        // We need to close and reopen the database connection so that the stats are
979a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        // taken into account. Make a note of it and do the actual reopening in the
980a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        // getWritableDatabase method.
981a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        mReopenDatabase = true;
982a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
983a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        ContentResolver.requestSync(null /* all accounts */,
984a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                ContactsContract.AUTHORITY, new Bundle());
985a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    }
986a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
987d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    private void createDirectoriesTable(SQLiteDatabase db) {
988d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DIRECTORIES + "(" +
989d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
990d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.PACKAGE_NAME + " TEXT NOT NULL," +
991d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.DIRECTORY_AUTHORITY + " TEXT NOT NULL," +
992d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.TYPE_RESOURCE_ID + " INTEGER," +
993d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.ACCOUNT_TYPE + " TEXT," +
994d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.ACCOUNT_NAME + " TEXT," +
995d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.DISPLAY_NAME + " TEXT, " +
996d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.EXPORT_SUPPORT + " INTEGER NOT NULL" +
99797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                        " DEFAULT " + Directory.EXPORT_SUPPORT_NONE + "," +
99897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                Directory.SHORTCUT_SUPPORT + " INTEGER NOT NULL" +
9993d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        " DEFAULT " + Directory.SHORTCUT_SUPPORT_NONE + "," +
10003d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                Directory.PHOTO_SUPPORT + " INTEGER NOT NULL" +
10013d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        " DEFAULT " + Directory.PHOTO_SUPPORT_NONE +
1002d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        ");");
1003d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
1004d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        insertDefaultDirectory(db);
1005d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        insertLocalInvisibleDirectory(db);
10063d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
10073d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        // Trigger a full scan of directories in the system
10083d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        setProperty(db, ContactDirectoryManager.PROPERTY_DIRECTORY_SCAN_COMPLETE, "0");
1009d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    }
1010d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
1011d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    private void insertDefaultDirectory(SQLiteDatabase db) {
1012d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        ContentValues values = new ContentValues();
1013d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        values.put(Directory._ID, Directory.DEFAULT);
1014d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        values.put(Directory.PACKAGE_NAME, mContext.getApplicationInfo().packageName);
1015d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        values.put(Directory.DIRECTORY_AUTHORITY, ContactsContract.AUTHORITY);
1016d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        values.put(Directory.TYPE_RESOURCE_ID, R.string.default_directory);
1017d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        values.put(Directory.EXPORT_SUPPORT, Directory.EXPORT_SUPPORT_NONE);
101897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        values.put(Directory.SHORTCUT_SUPPORT, Directory.SHORTCUT_SUPPORT_FULL);
10193d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        values.put(Directory.PHOTO_SUPPORT, Directory.PHOTO_SUPPORT_FULL);
1020d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        db.insert(Tables.DIRECTORIES, null, values);
1021d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    }
1022d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
1023d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    private void insertLocalInvisibleDirectory(SQLiteDatabase db) {
1024d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        ContentValues values = new ContentValues();
1025d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        values.put(Directory._ID, Directory.LOCAL_INVISIBLE);
1026d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        values.put(Directory.PACKAGE_NAME, mContext.getApplicationInfo().packageName);
1027d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        values.put(Directory.DIRECTORY_AUTHORITY, ContactsContract.AUTHORITY);
1028d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        values.put(Directory.TYPE_RESOURCE_ID, R.string.local_invisible_directory);
1029d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        values.put(Directory.EXPORT_SUPPORT, Directory.EXPORT_SUPPORT_NONE);
103097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        values.put(Directory.SHORTCUT_SUPPORT, Directory.SHORTCUT_SUPPORT_FULL);
10313d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        values.put(Directory.PHOTO_SUPPORT, Directory.PHOTO_SUPPORT_FULL);
1032d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        db.insert(Tables.DIRECTORIES, null, values);
1033d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    }
1034d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
1035916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    private static void createContactsTriggers(SQLiteDatabase db) {
1036fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1037fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        /*
1038fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * Automatically delete Data rows when a raw contact is deleted.
1039fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         */
1040fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.RAW_CONTACTS + "_deleted;");
1041fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_deleted "
1042fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   BEFORE DELETE ON " + Tables.RAW_CONTACTS
1043fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1044fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.DATA
1045fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Data.RAW_CONTACT_ID
1046fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID + ";"
1047fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.AGGREGATION_EXCEPTIONS
1048fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + AggregationExceptions.RAW_CONTACT_ID1
1049fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID
1050fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "        OR " + AggregationExceptions.RAW_CONTACT_ID2
1051fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID + ";"
105235da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "   DELETE FROM " + Tables.VISIBLE_CONTACTS
105335da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
105435da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
105535da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
105635da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "           )=1;"
1057385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "   DELETE FROM " + Tables.DEFAULT_DIRECTORY
1058385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
1059385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
1060385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
1061385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "           )=1;"
1062fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.CONTACTS
1063fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
1064fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
1065fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
1066fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "           )=1;"
1067fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1068fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1069fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1070fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS contacts_times_contacted;");
10716c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        db.execSQL("DROP TRIGGER IF EXISTS raw_contacts_times_contacted;");
1072fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1073fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        /*
1074fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * Triggers that update {@link RawContacts#VERSION} when the contact is
1075fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * marked for deletion or any time a data row is inserted, updated or
1076fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * deleted.
1077fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         */
1078fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.RAW_CONTACTS + "_marked_deleted;");
1079fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_marked_deleted "
10807f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori                + "   AFTER UPDATE ON " + Tables.RAW_CONTACTS
1081fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1082fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1083fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET "
1084fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                +         RawContacts.VERSION + "=OLD." + RawContacts.VERSION + "+1 "
1085fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + RawContacts._ID
1086fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "       AND NEW." + RawContacts.DELETED + "!= OLD." + RawContacts.DELETED + ";"
1087fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1088fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1089fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.DATA + "_updated;");
10907f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_updated AFTER UPDATE ON " + Tables.DATA
1091fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1092fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.DATA
1093fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + Data.DATA_VERSION + "=OLD." + Data.DATA_VERSION + "+1 "
1094fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Data._ID + "=OLD." + Data._ID + ";"
1095fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1096fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + RawContacts.VERSION + "=" + RawContacts.VERSION + "+1 "
1097fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + Data.RAW_CONTACT_ID + ";"
1098fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1099fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1100fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.DATA + "_deleted;");
1101fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_deleted BEFORE DELETE ON " + Tables.DATA
1102fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1103fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1104fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + RawContacts.VERSION + "=" + RawContacts.VERSION + "+1 "
1105fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + Data.RAW_CONTACT_ID + ";"
1106fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.PHONE_LOOKUP
1107fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + PhoneLookupColumns.DATA_ID + "=OLD." + Data._ID + ";"
1108fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.STATUS_UPDATES
1109fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + StatusUpdatesColumns.DATA_ID + "=OLD." + Data._ID + ";"
1110fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.NAME_LOOKUP
1111fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + NameLookupColumns.DATA_ID + "=OLD." + Data._ID + ";"
1112fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1113fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1114fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1115fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.GROUPS + "_updated1;");
1116fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.GROUPS + "_updated1 "
11177f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori                + "   AFTER UPDATE ON " + Tables.GROUPS
1118fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1119fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.GROUPS
1120fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET "
1121fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                +         Groups.VERSION + "=OLD." + Groups.VERSION + "+1"
1122fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Groups._ID + "=OLD." + Groups._ID + ";"
1123fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1124fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov    }
1125fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1126916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    private static void createContactsIndexes(SQLiteDatabase db) {
1127916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
1128916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        db.execSQL("CREATE INDEX name_lookup_index ON " + Tables.NAME_LOOKUP + " (" +
1129916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.NORMALIZED_NAME + "," +
1130916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.NAME_TYPE + ", " +
1131916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID + ", " +
1132916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.DATA_ID +
1133916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        ");");
113404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
113504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS raw_contact_sort_key1_index");
113604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
113704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                RawContacts.SORT_KEY_PRIMARY +
113804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        ");");
113904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
114004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS raw_contact_sort_key2_index");
114104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key2_index ON " + Tables.RAW_CONTACTS + " (" +
114204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                RawContacts.SORT_KEY_ALTERNATIVE +
114304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        ");");
1144916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    }
1145916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov
1146a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    private static void createContactsViews(SQLiteDatabase db) {
1147a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.CONTACTS_ALL + ";");
1148a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.CONTACTS_RESTRICTED + ";");
1149a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.DATA_ALL + ";");
1150a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.DATA_RESTRICTED + ";");
1151a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_CONTACTS_ALL + ";");
1152a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_CONTACTS_RESTRICTED + ";");
1153a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_ENTITIES + ";");
1154a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_ENTITIES_RESTRICTED + ";");
1155a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.ENTITIES + ";");
1156a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.ENTITIES_RESTRICTED + ";");
1157a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
11584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String dataColumns =
11594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                Data.IS_PRIMARY + ", "
11604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.IS_SUPER_PRIMARY + ", "
11614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA_VERSION + ", "
11624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + PackagesColumns.PACKAGE + " AS " + Data.RES_PACKAGE + ","
11634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + MimetypesColumns.MIMETYPE + " AS " + Data.MIMETYPE + ", "
116497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + Data.IS_READ_ONLY + ", "
11654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA1 + ", "
11664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA2 + ", "
11674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA3 + ", "
11684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA4 + ", "
11694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA5 + ", "
11704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA6 + ", "
11714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA7 + ", "
11724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA8 + ", "
11734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA9 + ", "
11744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA10 + ", "
11754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA11 + ", "
11764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA12 + ", "
11774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA13 + ", "
11784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA14 + ", "
11794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA15 + ", "
11804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC1 + ", "
11814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC2 + ", "
11824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC3 + ", "
11834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC4;
11844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
11854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String syncColumns =
11864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AS " + RawContacts.ACCOUNT_NAME + ","
11874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AS " + RawContacts.ACCOUNT_TYPE + ","
11884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SOURCE_ID + " AS " + RawContacts.SOURCE_ID + ","
1189f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                + RawContactsColumns.CONCRETE_NAME_VERIFIED + " AS " + RawContacts.NAME_VERIFIED + ","
11904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_VERSION + " AS " + RawContacts.VERSION + ","
11914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DIRTY + " AS " + RawContacts.DIRTY + ","
11924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC1 + " AS " + RawContacts.SYNC1 + ","
11934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC2 + " AS " + RawContacts.SYNC2 + ","
11944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC3 + " AS " + RawContacts.SYNC3 + ","
11954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC4 + " AS " + RawContacts.SYNC4;
11964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
11973d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        String baseContactColumns =
11983d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                Contacts.HAS_PHONE_NUMBER + ", "
11993d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.NAME_RAW_CONTACT_ID + ", "
12003d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.LOOKUP_KEY + ", "
12013d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.PHOTO_ID + ", "
12023d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Clauses.CONTACT_VISIBLE + " AS " + Contacts.IN_VISIBLE_GROUP + ", "
12033d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + ContactsColumns.LAST_STATUS_UPDATE_ID;
12043d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
12054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactOptionColumns =
12064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.CONCRETE_CUSTOM_RINGTONE
12074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.CUSTOM_RINGTONE + ","
12084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL
12094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.SEND_TO_VOICEMAIL + ","
12104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_LAST_TIME_CONTACTED
12114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.LAST_TIME_CONTACTED + ","
12124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_TIMES_CONTACTED
12134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.TIMES_CONTACTED + ","
12144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_STARRED
12154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.STARRED;
12164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String contactNameColumns =
12185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "name_raw_contact." + RawContacts.DISPLAY_NAME_SOURCE
12195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_SOURCE + ", "
12205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.DISPLAY_NAME_PRIMARY
12215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_PRIMARY + ", "
12225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.DISPLAY_NAME_ALTERNATIVE
12235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_ALTERNATIVE + ", "
12245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.PHONETIC_NAME
12255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.PHONETIC_NAME + ", "
12265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.PHONETIC_NAME_STYLE
12275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.PHONETIC_NAME_STYLE + ", "
12285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.SORT_KEY_PRIMARY
12295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.SORT_KEY_PRIMARY + ", "
12305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.SORT_KEY_ALTERNATIVE
12314394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        + " AS " + Contacts.SORT_KEY_ALTERNATIVE;
12325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
12334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String dataSelect = "SELECT "
12344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + Data._ID + ","
12354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.RAW_CONTACT_ID + ", "
1236fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + RawContacts.CONTACT_ID + ", "
12374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + syncColumns + ", "
12384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + dataColumns + ", "
12394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + contactOptionColumns + ", "
12405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + contactNameColumns + ", "
12413d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + baseContactColumns + ", "
12423d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
12433d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_URI) + ", "
12443d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
12453d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_THUMBNAIL_URI) + ", "
12464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
12474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.DATA
1248a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.MIMETYPES + " ON ("
12494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1250a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " ON ("
12514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1252a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.CONTACTS + " ON ("
1253fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   RawContactsColumns.CONCRETE_CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID + ")"
1254fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1255fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")"
1256a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1257a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
12584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
12594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1260f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1261a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                        + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
12624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.DATA_ALL + " AS " + dataSelect);
12644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.DATA_RESTRICTED + " AS " + dataSelect + " WHERE "
1265fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0");
12664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String rawContactOptionColumns =
12684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                RawContacts.CUSTOM_RINGTONE + ","
12694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.SEND_TO_VOICEMAIL + ","
12704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.LAST_TIME_CONTACTED + ","
12714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.TIMES_CONTACTED + ","
12724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.STARRED;
12734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String rawContactsSelect = "SELECT "
12754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + RawContacts._ID + ","
12764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.CONTACT_ID + ", "
12774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.AGGREGATION_MODE + ", "
127897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + RawContacts.RAW_CONTACT_IS_READ_ONLY + ", "
12794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.DELETED + ", "
12805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_SOURCE  + ", "
12815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_PRIMARY  + ", "
12825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_ALTERNATIVE  + ", "
12835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.PHONETIC_NAME  + ", "
12845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.PHONETIC_NAME_STYLE  + ", "
12855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.SORT_KEY_PRIMARY  + ", "
12865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.SORT_KEY_ALTERNATIVE + ", "
12874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + rawContactOptionColumns + ", "
12884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + syncColumns
12894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS;
12904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_CONTACTS_ALL + " AS " + rawContactsSelect);
12924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_CONTACTS_RESTRICTED + " AS " + rawContactsSelect
12934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " WHERE " + RawContacts.IS_RESTRICTED + "=0");
12944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactsColumns =
12964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.CONCRETE_CUSTOM_RINGTONE
12974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.CUSTOM_RINGTONE + ", "
12985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + contactNameColumns + ", "
12993d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + baseContactColumns + ", "
13004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_LAST_TIME_CONTACTED
13014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.LAST_TIME_CONTACTED + ", "
13024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL
13034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.SEND_TO_VOICEMAIL + ", "
13044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_STARRED
13054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.STARRED + ", "
13064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_TIMES_CONTACTED
13073d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        + " AS " + Contacts.TIMES_CONTACTED;
13084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactsSelect = "SELECT "
13104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_ID + " AS " + Contacts._ID + ","
13113d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + contactsColumns + ", "
13123d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(ContactsColumns.CONCRETE_ID, Contacts.PHOTO_URI) + ", "
13133d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(ContactsColumns.CONCRETE_ID, Contacts.PHOTO_THUMBNAIL_URI)
13144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.CONTACTS
1315fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1316fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")";
13174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.CONTACTS_ALL + " AS " + contactsSelect);
1319fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.CONTACTS_RESTRICTED + " AS " + contactsSelect
1320fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " WHERE " + ContactsColumns.SINGLE_IS_RESTRICTED + "=0");
1321a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1322a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        String rawEntitiesSelect = "SELECT "
1323a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContacts.CONTACT_ID + ", "
1324a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DELETED + " AS " + RawContacts.DELETED + ","
1325a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + dataColumns + ", "
1326a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + syncColumns + ", "
1327a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC1 + ", "
1328a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC2 + ", "
1329a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC3 + ", "
1330a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC4 + ", "
1331a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + RawContacts._ID + ", "
1332a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + RawContacts.Entity.DATA_ID + ","
1333a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_STARRED + " AS " + RawContacts.STARRED + ","
1334a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED + " AS "
1335a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                        + RawContacts.IS_RESTRICTED + ","
1336a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
1337a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS
1338a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.DATA + " ON ("
1339a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1340a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1341a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
1342a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.MIMETYPES + " ON ("
1343a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1344a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
1345a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1346a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1347a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
1348a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1349a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_ENTITIES + " AS "
1350a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + rawEntitiesSelect);
1351a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_ENTITIES_RESTRICTED + " AS "
1352a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + rawEntitiesSelect + " WHERE " + RawContacts.IS_RESTRICTED + "=0");
1353a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1354a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        String entitiesSelect = "SELECT "
1355a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + Contacts._ID + ", "
1356a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + RawContacts.CONTACT_ID + ", "
1357a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DELETED + " AS " + RawContacts.DELETED + ","
1358a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED
1359a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                        + " AS " + RawContacts.IS_RESTRICTED + ","
1360a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + dataColumns + ", "
1361a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + syncColumns + ", "
1362a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + contactsColumns + ", "
13633d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
13643d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_URI) + ", "
13653d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
13663d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_THUMBNAIL_URI) + ", "
1367a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC1 + ", "
1368a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC2 + ", "
1369a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC3 + ", "
1370a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC4 + ", "
1371a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + Contacts.Entity.RAW_CONTACT_ID + ", "
1372a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + Contacts.Entity.DATA_ID + ","
1373a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
1374a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS
1375a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " JOIN " + Tables.CONTACTS + " ON ("
1376a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   RawContactsColumns.CONCRETE_CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID + ")"
1377a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1378a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")"
1379a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.DATA + " ON ("
1380a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1381a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1382a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
1383a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.MIMETYPES + " ON ("
1384a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1385a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
1386a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1387a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1388a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
1389a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1390a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.ENTITIES + " AS "
1391a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + entitiesSelect);
1392a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.ENTITIES_RESTRICTED + " AS "
1393a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + entitiesSelect + " WHERE " + RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0");
1394a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    }
13954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13963d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    private static String buildPhotoUriAlias(String contactIdColumn, String alias) {
13972b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        return "(CASE WHEN " + Contacts.PHOTO_ID + " IS NULL"
13982b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " OR " + Contacts.PHOTO_ID + "=0"
13992b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " THEN NULL"
14002b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " ELSE " + "'" + Contacts.CONTENT_URI + "/'||"
14012b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                        + contactIdColumn + "|| '/" + Photo.CONTENT_DIRECTORY + "'"
14022b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " END)"
14032b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " AS " + alias;
14043d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
14053d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
1406a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    private static void createGroupsView(SQLiteDatabase db) {
1407a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.GROUPS_ALL + ";");
140889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        String groupsColumns =
140989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                Groups.ACCOUNT_NAME + ","
141089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.ACCOUNT_TYPE + ","
141189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SOURCE_ID + ","
141289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.VERSION + ","
141389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.DIRTY + ","
141489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.TITLE + ","
141589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.TITLE_RES + ","
141689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.NOTES + ","
141789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYSTEM_ID + ","
141889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.DELETED + ","
141989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.GROUP_VISIBLE + ","
142089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SHOULD_SYNC + ","
1421dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + Groups.AUTO_ADD + ","
1422dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + Groups.FAVORITES + ","
142389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC1 + ","
142489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC2 + ","
142589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC3 + ","
142689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC4 + ","
142789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + PackagesColumns.PACKAGE + " AS " + Groups.RES_PACKAGE;
142889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
142989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        String groupsSelect = "SELECT "
143089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + GroupsColumns.CONCRETE_ID + " AS " + Groups._ID + ","
143189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + groupsColumns
143289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + " FROM " + Tables.GROUPS_JOIN_PACKAGES;
143389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
143489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.GROUPS_ALL + " AS " + groupsSelect);
1435b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
1436b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1437b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
1438b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
143946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion < 99) {
144046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion
144146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana                    + ", data will be lost!");
144246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
144346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.CONTACTS + ";");
144446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.RAW_CONTACTS + ";");
144546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.PACKAGES + ";");
144646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.MIMETYPES + ";");
144746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.DATA + ";");
144846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.PHONE_LOOKUP + ";");
144946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.NAME_LOOKUP + ";");
145046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.NICKNAME_LOOKUP + ";");
145146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.GROUPS + ";");
145246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.ACTIVITIES + ";");
145346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.CALLS + ";");
145446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.SETTINGS + ";");
145546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.STATUS_UPDATES + ";");
145646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
145746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // TODO: we should not be dropping agg_exceptions and contact_options. In case that
145846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // table's schema changes, we should try to preserve the data, because it was entered
145946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // by the user and has never been synched to the server.
146046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.AGGREGATION_EXCEPTIONS + ";");
146146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
146246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            onCreate(db);
146346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            return;
146446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
1465f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
146646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion);
1467a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
146808e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        boolean upgradeViewsAndTriggers = false;
146904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        boolean upgradeNameLookup = false;
147008e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov
147146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion == 99) {
147208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
147346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            oldVersion++;
147446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
147546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
1476a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        if (oldVersion == 100) {
1477a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            db.execSQL("CREATE INDEX IF NOT EXISTS mimetypes_mimetype_index ON "
1478a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                    + Tables.MIMETYPES + " ("
1479a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                            + MimetypesColumns.MIMETYPE + ","
1480a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                            + MimetypesColumns._ID + ");");
1481a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            updateIndexStats(db, Tables.MIMETYPES,
1482a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                    "mimetypes_mimetype_index", "50 1 1");
1483a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
148408e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1485a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            oldVersion++;
1486a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        }
1487a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1488fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        if (oldVersion == 101) {
148908e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1490fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov            oldVersion++;
1491fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        }
1492fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
149347ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov        if (oldVersion == 102) {
149408e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
149547ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov            oldVersion++;
149647ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov        }
149747ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov
149836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        if (oldVersion == 103) {
149908e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1500bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey            oldVersion++;
1501bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey        }
1502bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey
150371037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov        if (oldVersion == 104 || oldVersion == 201) {
150471037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov            LegacyApiSupport.createSettingsTable(db);
150508e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
15063410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov            oldVersion++;
15073410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov        }
15083410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov
150971037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov        if (oldVersion == 105) {
15105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion202(db);
151104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            upgradeNameLookup = true;
15123410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov            oldVersion = 202;
151336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        }
151436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
1515fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        if (oldVersion == 202) {
15165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion203(db);
151708e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1518fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov            oldVersion++;
1519fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        }
1520fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
15219b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori        if (oldVersion == 203) {
152208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
15239b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori            oldVersion++;
15249b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori        }
15259b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori
15265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (oldVersion == 204) {
15275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion205(db);
152808e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
15295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            oldVersion++;
15305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
15315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
1532f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        if (oldVersion == 205) {
1533f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            upgrateToVersion206(db);
1534f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1535f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            oldVersion++;
1536f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        }
1537f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov
153831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        if (oldVersion == 206) {
1539b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeToVersion300(db);
154034469970fb04b9b188b5430f592b0c956a6ea2aaDmitri Plotnikov            oldVersion = 300;
154131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
154231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
15436c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        if (oldVersion == 300) {
15446c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook            upgradeViewsAndTriggers = true;
15456c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook            oldVersion = 301;
15466c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        }
15476c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook
1548916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        if (oldVersion == 301) {
1549916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1550916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            oldVersion = 302;
1551916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        }
1552916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov
1553b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (oldVersion == 302) {
1554b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeEmailToVersion303(db);
1555b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeNicknameToVersion303(db);
1556b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            oldVersion = 303;
1557b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
1558b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
155908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        if (oldVersion == 303) {
156008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            upgradeToVersion304(db);
156108768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            oldVersion = 304;
156208768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        }
156308768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
1564f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        if (oldVersion == 304) {
1565f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee            upgradeNameLookup = true;
1566f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee            oldVersion = 305;
1567f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        }
1568f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee
156960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        if (oldVersion == 305) {
157060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            upgradeToVersion306(db);
157160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            oldVersion = 306;
157260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        }
157360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
1574b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        if (oldVersion == 306) {
1575b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            upgradeToVersion307(db);
1576b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            oldVersion = 307;
1577b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        }
1578b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
1579743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        if (oldVersion == 307) {
1580743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov            upgradeToVersion308(db);
1581743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov            oldVersion = 308;
1582743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        }
1583743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
158494c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        // Gingerbread upgrades
158594c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        if (oldVersion < 350) {
1586afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann            upgradeViewsAndTriggers = true;
158794c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            oldVersion = 351;
1588afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann        }
1589afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann
159094c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        if (oldVersion == 351) {
159194c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            upgradeNameLookup = true;
159294c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            oldVersion = 352;
159380d7871ca31d604cbfd857661d5300bb090076dbDaniel Lehmann        }
159480d7871ca31d604cbfd857661d5300bb090076dbDaniel Lehmann
1595f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        // Honeycomb upgrades
1596f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        if (oldVersion < 400) {
1597dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana            upgradeViewsAndTriggers = true;
1598f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov            upgradeToVersion400(db);
1599f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov            oldVersion = 400;
1600dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        }
1601dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana
1602f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        if (oldVersion == 400) {
16034394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            upgradeViewsAndTriggers = true;
16044394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            upgradeToVersion401(db);
16054394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            oldVersion = 401;
16064394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        }
16074394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
1608d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        if (oldVersion == 401) {
1609d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov            upgradeToVersion402(db);
1610d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov            oldVersion = 402;
1611d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        }
1612d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
161397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        if (oldVersion == 402) {
161497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            upgradeViewsAndTriggers = true;
161597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            upgradeToVersion403(db);
161697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            oldVersion = 403;
161797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        }
161897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
1619a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        if (oldVersion == 403) {
1620a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1621a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov            oldVersion = 404;
1622a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        }
1623a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1624892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (oldVersion == 404) {
1625892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1626892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            upgradeToVersion405(db);
1627892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            oldVersion = 405;
1628892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
1629892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
16302530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        if (oldVersion == 405) {
16312530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            upgradeViewsAndTriggers = true;
16322530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            upgradeToVersion406(db);
16332530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            oldVersion = 406;
16342530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        }
16352530512f639c4979fd7371c7dd25dd67e8118124Bai Tao
1636cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov        if (oldVersion == 406) {
1637cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1638cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov            oldVersion = 407;
1639cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov        }
1640cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov
1641385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        if (oldVersion == 407) {
1642385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            upgradeToVersion408(db);
1643385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            oldVersion = 408;
1644385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        }
1645385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
16463d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        if (oldVersion == 408) {
16473d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            upgradeViewsAndTriggers = true;
16483d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            upgradeToVersion409(db);
16493d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            oldVersion = 409;
16503d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        }
16513d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
16522b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        if (oldVersion == 409) {
16532b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov            upgradeViewsAndTriggers = true;
16542b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov            oldVersion = 410;
16552b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        }
16562b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov
165708e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        if (upgradeViewsAndTriggers) {
165808e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createContactsViews(db);
165908e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createGroupsView(db);
166008e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createContactsTriggers(db);
1661916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            createContactsIndexes(db);
166208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            LegacyApiSupport.createViews(db);
1663916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            updateSqliteStats(db);
1664916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            mReopenDatabase = true;
166508e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        }
166608e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov
166704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (upgradeNameLookup) {
166804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            rebuildNameLookup(db);
166904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
167004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
167146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion != newVersion) {
167246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            throw new IllegalStateException(
167346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana                    "error upgrading the database to version " + newVersion);
167446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
1675b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
1676b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
16775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion202(SQLiteDatabase db) {
167836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL(
167936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "ALTER TABLE " + Tables.PHONE_LOOKUP +
168036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " ADD " + PhoneLookupColumns.MIN_MATCH + " TEXT;");
168136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
168236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
168336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
168436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
168536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
168636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        ");");
168736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
168836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        updateIndexStats(db, Tables.PHONE_LOOKUP,
168936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "phone_lookup_min_match_index", "10000 2 2 1");
169036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
169136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        SQLiteStatement update = db.compileStatement(
169236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "UPDATE " + Tables.PHONE_LOOKUP +
169336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " SET " + PhoneLookupColumns.MIN_MATCH + "=?" +
169436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " WHERE " + PhoneLookupColumns.DATA_ID + "=?");
169536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
169636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        // Populate the new column
169736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        Cursor c = db.query(Tables.PHONE_LOOKUP + " JOIN " + Tables.DATA +
169836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " ON (" + PhoneLookupColumns.DATA_ID + "=" + DataColumns.CONCRETE_ID + ")",
169936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                new String[]{Data._ID, Phone.NUMBER}, null, null, null, null, null);
170036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        try {
170136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            while (c.moveToNext()) {
170236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                long dataId = c.getLong(0);
170336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                String number = c.getString(1);
170436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                if (!TextUtils.isEmpty(number)) {
170536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.bindString(1, PhoneNumberUtils.toCallerIDMinMatch(number));
170636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.bindLong(2, dataId);
170736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.execute();
170836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                }
170936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            }
171036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        } finally {
171136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            c.close();
171236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        }
171336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    }
171436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
17155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion203(SQLiteDatabase db) {
1716758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // Garbage-collect first. A bug in Eclair was sometimes leaving
1717758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // raw_contacts in the database that no longer had contacts associated
1718758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // with them.  To avoid failures during this database upgrade, drop
1719758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // the orphaned raw_contacts.
1720758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        db.execSQL(
1721758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                "DELETE FROM raw_contacts" +
1722758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                " WHERE contact_id NOT NULL" +
1723758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                " AND contact_id NOT IN (SELECT _id FROM contacts)");
1724758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov
1725fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1726fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "ALTER TABLE " + Tables.CONTACTS +
1727fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " ADD " + Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)");
1728fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1729fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "ALTER TABLE " + Tables.RAW_CONTACTS +
17304394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " ADD contact_in_visible_group INTEGER NOT NULL DEFAULT 0");
1731fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1732fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // For each Contact, find the RawContact that contributed the display name
1733fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1734fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1735fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.NAME_RAW_CONTACT_ID + "=(" +
1736fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " SELECT " + RawContacts._ID +
1737fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.RAW_CONTACTS +
1738fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
1739fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " AND " + RawContactsColumns.CONCRETE_DISPLAY_NAME + "=" +
1740fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                                Tables.CONTACTS + "." + Contacts.DISPLAY_NAME +
1741fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " ORDER BY " + RawContacts._ID +
1742fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " LIMIT 1)"
1743fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1744fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1745fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_name_raw_contact_id_index ON " + Tables.CONTACTS + " (" +
1746fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID +
1747fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1748fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1749fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // If for some unknown reason we missed some names, let's make sure there are
1750fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // no contacts without a name, picking a raw contact "at random".
1751fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1752fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1753fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.NAME_RAW_CONTACT_ID + "=(" +
1754fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " SELECT " + RawContacts._ID +
1755fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.RAW_CONTACTS +
1756fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
1757fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " ORDER BY " + RawContacts._ID +
1758fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " LIMIT 1)" +
1759fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " WHERE " + Contacts.NAME_RAW_CONTACT_ID + " IS NULL"
1760fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1761fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1762fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // Wipe out DISPLAY_NAME on the Contacts table as it is no longer in use.
1763fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1764fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1765fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.DISPLAY_NAME + "=NULL"
1766fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1767fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1768fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // Copy the IN_VISIBLE_GROUP flag down to all raw contacts to allow
1769fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // indexing on (display_name, in_visible_group)
1770fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1771fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.RAW_CONTACTS +
17724394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " SET contact_in_visible_group=(" +
1773fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        "SELECT " + Contacts.IN_VISIBLE_GROUP +
1774fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.CONTACTS +
1775bcbd6a5cdd2d1aa6531c592428dc20e0282486c3Dmitri Plotnikov                        " WHERE " + Contacts._ID + "=" + RawContacts.CONTACT_ID + ")" +
1776bcbd6a5cdd2d1aa6531c592428dc20e0282486c3Dmitri Plotnikov                " WHERE " + RawContacts.CONTACT_ID + " NOT NULL"
1777fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1778fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1779fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
17804394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
1781fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                RawContactsColumns.DISPLAY_NAME + " COLLATE LOCALIZED ASC" +
1782fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1783fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1784fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("DROP INDEX contacts_visible_index");
1785fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_visible_index ON " + Tables.CONTACTS + " (" +
1786fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.IN_VISIBLE_GROUP +
1787fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1788fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov    }
1789fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
17905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion205(SQLiteDatabase db) {
17915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
17925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.DISPLAY_NAME_ALTERNATIVE + " TEXT;");
17935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
17945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.PHONETIC_NAME + " TEXT;");
17955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
17965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.PHONETIC_NAME_STYLE + " INTEGER;");
17975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
1798de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " ADD " + RawContacts.SORT_KEY_PRIMARY
1799de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " TEXT COLLATE " + ContactsProvider2.PHONEBOOK_COLLATOR_NAME + ";");
18005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
1801de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " ADD " + RawContacts.SORT_KEY_ALTERNATIVE
1802de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " TEXT COLLATE " + ContactsProvider2.PHONEBOOK_COLLATOR_NAME + ";");
18035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        final Locale locale = Locale.getDefault();
18055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
180651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        NameSplitter splitter = createNameSplitter();
18075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement rawContactUpdate = db.compileStatement(
18095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.RAW_CONTACTS +
18105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
18115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.DISPLAY_NAME_PRIMARY + "=?," +
18125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," +
18135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.PHONETIC_NAME + "=?," +
18145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.PHONETIC_NAME_STYLE + "=?," +
18155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.SORT_KEY_PRIMARY + "=?," +
18165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.SORT_KEY_ALTERNATIVE + "=?" +
18175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + RawContacts._ID + "=?");
18185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        upgradeStructuredNamesToVersion205(db, rawContactUpdate, splitter);
18205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        upgradeOrganizationsToVersion205(db, rawContactUpdate, splitter);
18215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("DROP INDEX raw_contact_sort_key1_index");
18235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
18244394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
18255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.SORT_KEY_PRIMARY +
18265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        ");");
18275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key2_index ON " + Tables.RAW_CONTACTS + " (" +
18294394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
18305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.SORT_KEY_ALTERNATIVE +
18315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        ");");
18325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
18335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private interface StructName205Query {
18355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String TABLE = Tables.DATA_JOIN_RAW_CONTACTS;
18365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String COLUMNS[] = {
18385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.CONCRETE_ID,
18395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Data.RAW_CONTACT_ID,
18405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_SOURCE,
18415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_PRIMARY,
18425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PREFIX,
18435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.GIVEN_NAME,
18445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.MIDDLE_NAME,
18455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.FAMILY_NAME,
18465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.SUFFIX,
18475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_FAMILY_NAME,
18485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_MIDDLE_NAME,
18495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_GIVEN_NAME,
18505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        };
18515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int ID = 0;
18535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int RAW_CONTACT_ID = 1;
18545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int DISPLAY_NAME_SOURCE = 2;
18555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int DISPLAY_NAME = 3;
18565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PREFIX = 4;
18575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int GIVEN_NAME = 5;
18585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int MIDDLE_NAME = 6;
18595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int FAMILY_NAME = 7;
18605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int SUFFIX = 8;
18615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_FAMILY_NAME = 9;
18625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_MIDDLE_NAME = 10;
18635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_GIVEN_NAME = 11;
18645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
18655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeStructuredNamesToVersion205(SQLiteDatabase db,
18675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement rawContactUpdate, NameSplitter splitter) {
18685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        // Process structured names to detect the style of the full name and phonetic name
18705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        long mMimeType;
18725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
18735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            mMimeType = DatabaseUtils.longForQuery(db,
18745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    "SELECT " + MimetypesColumns._ID +
18755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    " FROM " + Tables.MIMETYPES +
18765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    " WHERE " + MimetypesColumns.MIMETYPE
18775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                            + "='" + StructuredName.CONTENT_ITEM_TYPE + "'", null);
18785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } catch (SQLiteDoneException e) {
18795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            // No structured names in the database
18805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            return;
18815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
18825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement structuredNameUpdate = db.compileStatement(
18845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.DATA +
18855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
18865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.FULL_NAME_STYLE + "=?," +
18875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.DISPLAY_NAME + "=?," +
18885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.PHONETIC_NAME_STYLE + "=?" +
18895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + Data._ID + "=?");
18905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        NameSplitter.Name name = new NameSplitter.Name();
18925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        StringBuilder sb = new StringBuilder();
18935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        Cursor cursor = db.query(StructName205Query.TABLE,
18945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructName205Query.COLUMNS,
18955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=" + mMimeType, null, null, null, null);
18965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
18975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            while (cursor.moveToNext()) {
18985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long dataId = cursor.getLong(StructName205Query.ID);
18995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long rawContactId = cursor.getLong(StructName205Query.RAW_CONTACT_ID);
19005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                int displayNameSource = cursor.getInt(StructName205Query.DISPLAY_NAME_SOURCE);
19015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String displayName = cursor.getString(StructName205Query.DISPLAY_NAME);
19025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.clear();
19045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.prefix = cursor.getString(StructName205Query.PREFIX);
19055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.givenNames = cursor.getString(StructName205Query.GIVEN_NAME);
19065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.middleName = cursor.getString(StructName205Query.MIDDLE_NAME);
19075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.familyName = cursor.getString(StructName205Query.FAMILY_NAME);
19085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.suffix = cursor.getString(StructName205Query.SUFFIX);
19095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticFamilyName = cursor.getString(StructName205Query.PHONETIC_FAMILY_NAME);
19105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticMiddleName = cursor.getString(StructName205Query.PHONETIC_MIDDLE_NAME);
19115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticGivenName = cursor.getString(StructName205Query.PHONETIC_GIVEN_NAME);
19125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                upgradeNameToVersion205(dataId, rawContactId, displayNameSource, displayName, name,
19145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        structuredNameUpdate, rawContactUpdate, splitter, sb);
19155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
19165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } finally {
19175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            cursor.close();
19185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
19195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
19205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeNameToVersion205(long dataId, long rawContactId, int displayNameSource,
19225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String currentDisplayName, NameSplitter.Name name,
19235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement structuredNameUpdate, SQLiteStatement rawContactUpdate,
19245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            NameSplitter splitter, StringBuilder sb) {
19255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        splitter.guessNameStyle(name);
1927ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        int unadjustedFullNameStyle = name.fullNameStyle;
19285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        name.fullNameStyle = splitter.getAdjustedFullNameStyle(name.fullNameStyle);
19295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String displayName = splitter.join(name, true);
19305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
1931ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        // Don't update database with the adjusted fullNameStyle as it is locale
1932ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        // related
1933ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        structuredNameUpdate.bindLong(1, unadjustedFullNameStyle);
19345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        DatabaseUtils.bindObjectToProgram(structuredNameUpdate, 2, displayName);
19355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.bindLong(3, name.phoneticNameStyle);
19365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.bindLong(4, dataId);
19375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.execute();
19385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (displayNameSource == DisplayNameSources.STRUCTURED_NAME) {
19405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String displayNameAlternative = splitter.join(name, false);
19415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String phoneticName = splitter.joinPhoneticName(name);
19425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String sortKey = null;
19435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String sortKeyAlternative = null;
19445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            if (phoneticName != null) {
19465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKey = sortKeyAlternative = phoneticName;
1947ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao            } else if (name.fullNameStyle == FullNameStyle.CHINESE ||
1948ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                    name.fullNameStyle == FullNameStyle.CJK) {
1949ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                sortKey = sortKeyAlternative = ContactLocaleUtils.getIntance()
1950ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                        .getSortKey(displayName, name.fullNameStyle);
19515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
19525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            if (sortKey == null) {
19545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKey = displayName;
19555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKeyAlternative = displayNameAlternative;
19565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
19575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            updateRawContact205(rawContactUpdate, rawContactId, displayName,
19595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    displayNameAlternative, name.phoneticNameStyle, phoneticName, sortKey,
19605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    sortKeyAlternative);
19615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
19625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
19635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private interface Organization205Query {
19655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String TABLE = Tables.DATA_JOIN_RAW_CONTACTS;
19665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String COLUMNS[] = {
19685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.CONCRETE_ID,
19695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Data.RAW_CONTACT_ID,
19705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Organization.COMPANY,
19715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Organization.PHONETIC_NAME,
19725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        };
19735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int ID = 0;
19755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int RAW_CONTACT_ID = 1;
19765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int COMPANY = 2;
19775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_NAME = 3;
19785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
19795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeOrganizationsToVersion205(SQLiteDatabase db,
19815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement rawContactUpdate, NameSplitter splitter) {
1982b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeType = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
19835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement organizationUpdate = db.compileStatement(
19855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.DATA +
19865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
19875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        Organization.PHONETIC_NAME_STYLE + "=?" +
19885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + Data._ID + "=?");
19895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        Cursor cursor = db.query(Organization205Query.TABLE, Organization205Query.COLUMNS,
1991b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=" + mimeType + " AND "
19925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + RawContacts.DISPLAY_NAME_SOURCE + "=" + DisplayNameSources.ORGANIZATION,
19935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                null, null, null, null);
19945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
19955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            while (cursor.moveToNext()) {
19965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long dataId = cursor.getLong(Organization205Query.ID);
19975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long rawContactId = cursor.getLong(Organization205Query.RAW_CONTACT_ID);
19985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String company = cursor.getString(Organization205Query.COMPANY);
19995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String phoneticName = cursor.getString(Organization205Query.PHONETIC_NAME);
20005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                int phoneticNameStyle = splitter.guessPhoneticNameStyle(phoneticName);
20025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.bindLong(1, phoneticNameStyle);
20045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.bindLong(2, dataId);
20055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.execute();
20065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String sortKey = null;
20085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                if (phoneticName == null && company != null) {
20095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    int nameStyle = splitter.guessFullNameStyle(company);
20105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    nameStyle = splitter.getAdjustedFullNameStyle(nameStyle);
2011ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                    if (nameStyle == FullNameStyle.CHINESE ||
2012ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                            nameStyle == FullNameStyle.CJK ) {
2013ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                        sortKey = ContactLocaleUtils.getIntance()
2014ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                                .getSortKey(company, nameStyle);
20155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    }
20165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                }
20175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                if (sortKey == null) {
20195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    sortKey = company;
20205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                }
20215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                updateRawContact205(rawContactUpdate, rawContactId, company,
20235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        company, phoneticNameStyle, phoneticName, sortKey, sortKey);
20245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
20255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } finally {
20265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            cursor.close();
20275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
20285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
20295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void updateRawContact205(SQLiteStatement rawContactUpdate, long rawContactId,
20315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String displayName, String displayNameAlternative, int phoneticNameStyle,
20325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String phoneticName, String sortKeyPrimary, String sortKeyAlternative) {
20335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 1, displayName);
20345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 2, displayNameAlternative);
20355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 3, phoneticName);
20365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.bindLong(4, phoneticNameStyle);
20375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 5, sortKeyPrimary);
20385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 6, sortKeyAlternative);
20395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.bindLong(7, rawContactId);
20405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.execute();
20415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
20425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
2043f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov    private void upgrateToVersion206(SQLiteDatabase db) {
2044f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
2045f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                + " ADD " + RawContacts.NAME_VERIFIED + " INTEGER NOT NULL DEFAULT 0;");
2046f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov    }
2047f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov
204831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    private interface Organization300Query {
204931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String TABLE = Tables.DATA;
205031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
205131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String SELECTION = DataColumns.MIMETYPE_ID + "=?";
205231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
205331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String COLUMNS[] = {
205431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization._ID,
205531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.RAW_CONTACT_ID,
205631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.COMPANY,
205731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.TITLE
205831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        };
205931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
206031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int ID = 0;
206131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int RAW_CONTACT_ID = 1;
206231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int COMPANY = 2;
206331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int TITLE = 3;
206431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    }
206531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
206631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    /**
206731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     * Fix for the bug where name lookup records for organizations would get removed by
206831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     * unrelated updates of the data rows.
206931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     */
2070b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeToVersion300(SQLiteDatabase db) {
2071b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeType = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
2072b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeType == -1) {
207331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            return;
207431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
207531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
207631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        ContentValues values = new ContentValues();
207731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
207831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        // Find all data rows with the mime type "organization"
207931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        Cursor cursor = db.query(Organization300Query.TABLE, Organization300Query.COLUMNS,
2080b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Organization300Query.SELECTION, new String[] {String.valueOf(mimeType)},
208131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                null, null, null);
208231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        try {
208331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            while (cursor.moveToNext()) {
208431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                long dataId = cursor.getLong(Organization300Query.ID);
208531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                long rawContactId = cursor.getLong(Organization300Query.RAW_CONTACT_ID);
208631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                String company = cursor.getString(Organization300Query.COMPANY);
208731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                String title = cursor.getString(Organization300Query.TITLE);
208831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
208931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                // First delete name lookup if there is any (chances are there won't be)
209031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                db.delete(Tables.NAME_LOOKUP, NameLookupColumns.DATA_ID + "=?",
209131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                        new String[]{String.valueOf(dataId)});
209231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
209331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                // Now insert two name lookup records: one for company name, one for title
209431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.DATA_ID, dataId);
209531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
209631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.NAME_TYPE, NameLookupType.ORGANIZATION);
209731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
209831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                if (!TextUtils.isEmpty(company)) {
209931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME,
210031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                            NameNormalizer.normalize(company));
210131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
210231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                }
210331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
210431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                if (!TextUtils.isEmpty(title)) {
210531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME,
210631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                            NameNormalizer.normalize(title));
210731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
210831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                }
210931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            }
211031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        } finally {
211131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            cursor.close();
211231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
211331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    }
211431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
2115b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private static final class Upgrade303Query {
2116b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
2117b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2118b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String SELECTION =
2119b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=?" +
2120b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    " AND " + Data._ID + " NOT IN " +
2121b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    "(SELECT " + NameLookupColumns.DATA_ID + " FROM " + Tables.NAME_LOOKUP + ")" +
2122b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    " AND " + Data.DATA1 + " NOT NULL";
2123b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2124b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String COLUMNS[] = {
2125b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data._ID,
2126b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data.RAW_CONTACT_ID,
2127b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data.DATA1,
2128b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        };
2129b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2130b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int ID = 0;
2131b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
2132b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int DATA1 = 2;
2133b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2134b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2135b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    /**
2136b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * The {@link ContactsProvider2#update} method was deleting name lookup for new
2137b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * emails during the sync.  We need to restore the lost name lookup rows.
2138b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     */
2139b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeEmailToVersion303(SQLiteDatabase db) {
2140b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Email.CONTENT_ITEM_TYPE);
2141b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeTypeId == -1) {
2142b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return;
2143b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2144b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2145b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        ContentValues values = new ContentValues();
2146b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2147b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        // Find all data rows with the mime type "email" that are missing name lookup
2148b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Cursor cursor = db.query(Upgrade303Query.TABLE, Upgrade303Query.COLUMNS,
2149b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Upgrade303Query.SELECTION, new String[] {String.valueOf(mimeTypeId)},
2150b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                null, null, null);
2151b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2152b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            while (cursor.moveToNext()) {
2153b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long dataId = cursor.getLong(Upgrade303Query.ID);
2154b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long rawContactId = cursor.getLong(Upgrade303Query.RAW_CONTACT_ID);
2155b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                String value = cursor.getString(Upgrade303Query.DATA1);
2156b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                value = extractHandleFromEmailAddress(value);
2157b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2158b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                if (value != null) {
2159b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.DATA_ID, dataId);
2160b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
2161b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.NAME_TYPE, NameLookupType.EMAIL_BASED_NICKNAME);
2162b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME, NameNormalizer.normalize(value));
2163b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
2164b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                }
2165b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            }
2166b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } finally {
2167b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            cursor.close();
2168b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2169b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2170b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2171b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    /**
2172b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * The {@link ContactsProvider2#update} method was deleting name lookup for new
2173b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * nicknames during the sync.  We need to restore the lost name lookup rows.
2174b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     */
2175b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeNicknameToVersion303(SQLiteDatabase db) {
2176b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Nickname.CONTENT_ITEM_TYPE);
2177b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeTypeId == -1) {
2178b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return;
2179b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2180b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2181b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        ContentValues values = new ContentValues();
2182b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2183b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        // Find all data rows with the mime type "nickname" that are missing name lookup
2184b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Cursor cursor = db.query(Upgrade303Query.TABLE, Upgrade303Query.COLUMNS,
2185b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Upgrade303Query.SELECTION, new String[] {String.valueOf(mimeTypeId)},
2186b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                null, null, null);
2187b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2188b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            while (cursor.moveToNext()) {
2189b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long dataId = cursor.getLong(Upgrade303Query.ID);
2190b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long rawContactId = cursor.getLong(Upgrade303Query.RAW_CONTACT_ID);
2191b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                String value = cursor.getString(Upgrade303Query.DATA1);
2192b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2193b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.DATA_ID, dataId);
2194b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
2195b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.NAME_TYPE, NameLookupType.NICKNAME);
2196b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.NORMALIZED_NAME, NameNormalizer.normalize(value));
2197b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                db.insert(Tables.NAME_LOOKUP, null, values);
2198b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            }
2199b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } finally {
2200b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            cursor.close();
2201b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2202b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2203b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
220451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void upgradeToVersion304(SQLiteDatabase db) {
220551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        // Mimetype table requires an index on mime type
220651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS mime_type ON " + Tables.MIMETYPES + " (" +
220751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                MimetypesColumns.MIMETYPE +
220851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        ");");
220951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
221051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
221160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann    private void upgradeToVersion306(SQLiteDatabase db) {
221260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        // Fix invalid lookup that was used for Exchange contacts (it was not escaped)
221360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        // It happened when a new contact was created AND synchronized
221460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final StringBuilder lookupKeyBuilder = new StringBuilder();
221560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final SQLiteStatement updateStatement = db.compileStatement(
221660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "UPDATE contacts " +
221760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "SET lookup=? " +
221860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "WHERE _id=?");
221960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final Cursor contactIdCursor = db.rawQuery(
222060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "SELECT DISTINCT contact_id " +
222160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "FROM raw_contacts " +
222260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "WHERE deleted=0 AND account_type='com.android.exchange'",
222360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                null);
222460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        try {
222560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            while (contactIdCursor.moveToNext()) {
222660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                final long contactId = contactIdCursor.getLong(0);
222760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                lookupKeyBuilder.setLength(0);
222860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                final Cursor c = db.rawQuery(
222960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "SELECT account_type, account_name, _id, sourceid, display_name " +
223060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "FROM raw_contacts " +
223160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "WHERE contact_id=? " +
223260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "ORDER BY _id",
223360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        new String[] { String.valueOf(contactId) });
223460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                try {
223560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    while (c.moveToNext()) {
223660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        ContactLookupKey.appendToLookupKey(lookupKeyBuilder,
223760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(0),
223860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(1),
223960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getLong(2),
224060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(3),
224160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(4));
224260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    }
224360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                } finally {
224460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    c.close();
224560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                }
224660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
224760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                if (lookupKeyBuilder.length() == 0) {
224860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    updateStatement.bindNull(1);
224960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                } else {
225060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    updateStatement.bindString(1, Uri.encode(lookupKeyBuilder.toString()));
225160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                }
225260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                updateStatement.bindLong(2, contactId);
225360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
225460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                updateStatement.execute();
225560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            }
225660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        } finally {
225760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            updateStatement.close();
225860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            contactIdCursor.close();
225960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        }
226060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann    }
226160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
2262b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    private void upgradeToVersion307(SQLiteDatabase db) {
2263b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        db.execSQL("CREATE TABLE properties (" +
2264b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                "property_key TEXT PRIMARY_KEY, " +
2265b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                "property_value TEXT" +
2266b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ");");
2267b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
2268b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
2269743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov    private void upgradeToVersion308(SQLiteDatabase db) {
22704394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE accounts (" +
22714394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "account_name TEXT, " +
22724394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "account_type TEXT " +
22734394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
2274743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
22754394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO accounts " +
22764394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "SELECT DISTINCT account_name, account_type FROM raw_contacts");
2277743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov    }
2278743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
2279f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov    private void upgradeToVersion400(SQLiteDatabase db) {
2280dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        db.execSQL("ALTER TABLE " + Tables.GROUPS
2281dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + " ADD " + Groups.FAVORITES + " INTEGER NOT NULL DEFAULT 0;");
2282dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        db.execSQL("ALTER TABLE " + Tables.GROUPS
2283dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + " ADD " + Groups.AUTO_ADD + " INTEGER NOT NULL DEFAULT 0;");
2284dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana    }
2285dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana
228651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void rebuildNameLookup(SQLiteDatabase db) {
228751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
228851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        insertNameLookup(db);
228951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        createContactsIndexes(db);
229051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
229151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
229204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
229351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     * Regenerates all locale-sensitive data: nickname_lookup, name_lookup and sort keys.
229404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
229551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    public void setLocale(ContactsProvider2 provider, Locale locale) {
229651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        Log.i(TAG, "Switching to locale " + locale);
229704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
2298c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamilton        long start = SystemClock.uptimeMillis();
229951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
230051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.setLocale(locale);
230151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.beginTransaction();
230251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
230351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX raw_contact_sort_key1_index");
230451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX raw_contact_sort_key2_index");
230551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
230651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
230751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            loadNicknameLookupTable(db);
230851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertNameLookup(db);
230951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            rebuildSortKeys(db, provider);
231051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            createContactsIndexes(db);
231151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.setTransactionSuccessful();
231251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
231351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.endTransaction();
231451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
231551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
2316c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamilton        Log.i(TAG, "Locale change completed in " + (SystemClock.uptimeMillis() - start) + "ms");
231751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
231851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
231951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    /**
232051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     * Regenerates sort keys for all contacts.
232151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     */
232251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void rebuildSortKeys(SQLiteDatabase db, ContactsProvider2 provider) {
232351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        Cursor cursor = db.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID},
232451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                null, null, null, null, null);
232551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
232651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            while (cursor.moveToNext()) {
232751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                long rawContactId = cursor.getLong(0);
232851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                provider.updateRawContactDisplayName(db, rawContactId);
232951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            }
233051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
233151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            cursor.close();
233251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
233351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
233451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
233551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void insertNameLookup(SQLiteDatabase db) {
233604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NAME_LOOKUP);
233704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
233804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        SQLiteStatement nameLookupInsert = db.compileStatement(
233904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                "INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "("
234004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.RAW_CONTACT_ID + ","
234104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.DATA_ID + ","
234204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.NAME_TYPE + ","
234304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.NORMALIZED_NAME +
234404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                ") VALUES (?,?,?,?)");
234504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
234651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
234751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertStructuredNameLookup(db, nameLookupInsert);
234851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertOrganizationLookup(db, nameLookupInsert);
234951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertEmailLookup(db, nameLookupInsert);
235051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertNicknameLookup(db, nameLookupInsert);
235151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
235251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            nameLookupInsert.close();
235351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
235404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
235504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
235604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class StructuredNameQuery {
235704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
235804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
235904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
236004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
236104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
236204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
236304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName._ID,
236404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName.RAW_CONTACT_ID,
236504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName.DISPLAY_NAME,
236604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
236704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
236804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
236904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
237004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int DISPLAY_NAME = 2;
237104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
237204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
237304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private class StructuredNameLookupBuilder extends NameLookupBuilder {
237404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
237504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        private final SQLiteStatement mNameLookupInsert;
237604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        private final CommonNicknameCache mCommonNicknameCache;
237704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
237804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public StructuredNameLookupBuilder(NameSplitter splitter,
237904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                CommonNicknameCache commonNicknameCache, SQLiteStatement nameLookupInsert) {
238004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            super(splitter);
238104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            this.mCommonNicknameCache = commonNicknameCache;
238204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            this.mNameLookupInsert = nameLookupInsert;
238304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
238404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
238504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        @Override
238604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        protected void insertNameLookup(long rawContactId, long dataId, int lookupType,
238704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String name) {
238804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            if (!TextUtils.isEmpty(name)) {
238904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                ContactsDatabaseHelper.this.insertNormalizedNameLookup(mNameLookupInsert,
239004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        rawContactId, dataId, lookupType, name);
239104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
239204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
239304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
239404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        @Override
239504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        protected String[] getCommonNicknameClusters(String normalizedName) {
239604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return mCommonNicknameCache.getCommonNicknameClusters(normalizedName);
239704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
239804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
239904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
240004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
240104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all structured names in the database.
240204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
240304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertStructuredNameLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
2404d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov        NameSplitter nameSplitter = createNameSplitter();
2405d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov        NameLookupBuilder nameLookupBuilder = new StructuredNameLookupBuilder(nameSplitter,
240604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                new CommonNicknameCache(db), nameLookupInsert);
240704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, StructuredName.CONTENT_ITEM_TYPE);
240804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(StructuredNameQuery.TABLE, StructuredNameQuery.COLUMNS,
240904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredNameQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
241004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
241104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
241204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
241304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(StructuredNameQuery.ID);
241404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(StructuredNameQuery.RAW_CONTACT_ID);
241504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String name = cursor.getString(StructuredNameQuery.DISPLAY_NAME);
2416d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov                int fullNameStyle = nameSplitter.guessFullNameStyle(name);
241751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                fullNameStyle = nameSplitter.getAdjustedFullNameStyle(fullNameStyle);
2418d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov                nameLookupBuilder.insertNameLookup(rawContactId, dataId, name, fullNameStyle);
241904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
242004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
242104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
242204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
242304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
242404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
242504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class OrganizationQuery {
242604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
242704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
242804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
242904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
243004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
243104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
243204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization._ID,
243304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.RAW_CONTACT_ID,
243404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.COMPANY,
243504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.TITLE,
243604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
243704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
243804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
243904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
244004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int COMPANY = 2;
244104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int TITLE = 3;
244204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
244304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
244404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
244504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all organizations in the database.
244604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
244704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertOrganizationLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
244804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
244904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(OrganizationQuery.TABLE, OrganizationQuery.COLUMNS,
245004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                OrganizationQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
245104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
245204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
245304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
245404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(OrganizationQuery.ID);
245504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(OrganizationQuery.RAW_CONTACT_ID);
245604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String organization = cursor.getString(OrganizationQuery.COMPANY);
245704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String title = cursor.getString(OrganizationQuery.TITLE);
245804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
245904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.ORGANIZATION, organization);
246004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
246104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.ORGANIZATION, title);
246204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
246304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
246404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
246504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
246604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
246704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
246804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class EmailQuery {
246904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
247004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
247104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
247204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
247304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
247404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
247504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email._ID,
247604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email.RAW_CONTACT_ID,
247704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email.ADDRESS,
247804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
247904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
248004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
248104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
248204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ADDRESS = 2;
248304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
248404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
248504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
248604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all email addresses in the database.
248704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
248804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertEmailLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
248904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Email.CONTENT_ITEM_TYPE);
249004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(EmailQuery.TABLE, EmailQuery.COLUMNS,
249104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                EmailQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
249204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
249304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
249404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
249504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(EmailQuery.ID);
249604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(EmailQuery.RAW_CONTACT_ID);
249704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String address = cursor.getString(EmailQuery.ADDRESS);
249804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                address = extractHandleFromEmailAddress(address);
249904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
250004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.EMAIL_BASED_NICKNAME, address);
250104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
250204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
250304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
250404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
250504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
250604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
250704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class NicknameQuery {
250804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
250904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
251004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
251104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
251204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
251304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
251404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname._ID,
251504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname.RAW_CONTACT_ID,
251604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname.NAME,
251704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
251804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
251904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
252004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
252104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int NAME = 2;
252204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
252304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
252404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
252504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all nicknames in the database.
252604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
252704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertNicknameLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
252804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Nickname.CONTENT_ITEM_TYPE);
252904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(NicknameQuery.TABLE, NicknameQuery.COLUMNS,
253004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                NicknameQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
253104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
253204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
253304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
253404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(NicknameQuery.ID);
253504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(NicknameQuery.RAW_CONTACT_ID);
253604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String nickname = cursor.getString(NicknameQuery.NAME);
253704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
253804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.NICKNAME, nickname);
253904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
254004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
254104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
254204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
254304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
254404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
254504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
254604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts a record in the {@link Tables#NAME_LOOKUP} table.
254704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
254804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    public void insertNameLookup(SQLiteStatement stmt, long rawContactId, long dataId,
254904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            int lookupType, String name) {
255004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (TextUtils.isEmpty(name)) {
255104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return;
255204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
255304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
255404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        String normalized = NameNormalizer.normalize(name);
255504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (TextUtils.isEmpty(normalized)) {
255604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return;
255704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
255804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
255904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        insertNormalizedNameLookup(stmt, rawContactId, dataId, lookupType, normalized);
256004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
256104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
256204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertNormalizedNameLookup(SQLiteStatement stmt, long rawContactId, long dataId,
256304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            int lookupType, String normalizedName) {
256404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(1, rawContactId);
256504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(2, dataId);
256604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(3, lookupType);
256704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindString(4, normalizedName);
256804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.executeInsert();
256904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
257004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
25714394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    /**
25724394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov     * Changing the VISIBLE bit from a field on both RawContacts and Contacts to a separate table.
25734394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov     */
25744394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    private void upgradeToVersion401(SQLiteDatabase db) {
25754394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.VISIBLE_CONTACTS + " (" +
25764394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
25774394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
25784394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.VISIBLE_CONTACTS +
25794394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " SELECT " + Contacts._ID +
25804394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " FROM " + Tables.CONTACTS +
25814394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " WHERE " + Contacts.IN_VISIBLE_GROUP + "!=0");
25824394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("DROP INDEX contacts_visible_index");
25834394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    }
25844394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
2585d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    /**
2586d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov     * Introducing a new table: directories.
2587d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov     */
2588d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    private void upgradeToVersion402(SQLiteDatabase db) {
2589d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        createDirectoriesTable(db);
2590d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    }
2591d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
259297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    private void upgradeToVersion403(SQLiteDatabase db) {
259397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
259497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        createDirectoriesTable(db);
259597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
259697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("ALTER TABLE raw_contacts"
259797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + " ADD raw_contact_is_read_only INTEGER NOT NULL DEFAULT 0;");
259897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
259997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("ALTER TABLE data"
260097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + " ADD is_read_only INTEGER NOT NULL DEFAULT 0;");
260197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    }
260297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
2603892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    private void upgradeToVersion405(SQLiteDatabase db) {
2604892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS phone_lookup;");
2605892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        // Private phone numbers table used for lookup
2606892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" +
2607892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID
2608892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " INTEGER REFERENCES data(_id) NOT NULL," +
2609892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID
2610892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
2611892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL," +
2612892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL" +
2613892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2614892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2615892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" +
2616892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + "," +
2617892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
2618892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
2619892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2620892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2621892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
2622892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
2623892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
2624892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
2625892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2626892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2627892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Phone.CONTENT_ITEM_TYPE);
2628892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (mimeTypeId == -1) {
2629892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            return;
2630892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
2631892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2632892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        String mCountryIso = getCountryIso();
2633892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        Cursor cursor = db.rawQuery(
2634892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    "SELECT _id, " + Phone.RAW_CONTACT_ID + ", " + Phone.NUMBER +
2635892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    " FROM " + Tables.DATA +
2636892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId
2637892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                            + " AND " + Phone.NUMBER + " NOT NULL", null);
2638892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2639892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ContentValues phoneValues = new ContentValues();
2640892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        try {
2641892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            while (cursor.moveToNext()) {
2642892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                long dataID = cursor.getLong(0);
2643892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                long rawContactID = cursor.getLong(1);
2644892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String number = cursor.getString(2);
2645892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String numberE164 = PhoneNumberUtils.formatNumberToE164(number, mCountryIso);
2646892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String normalizedNumber = PhoneNumberUtils.normalizeNumber(number);
2647892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                if (!TextUtils.isEmpty(normalizedNumber)) {
2648892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.clear();
2649892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactID);
2650892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.DATA_ID, dataID);
2651892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber);
2652892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.MIN_MATCH,
2653892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                            PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber));
2654892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    db.insert(Tables.PHONE_LOOKUP, null, phoneValues);
2655892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2656892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    if (numberE164 != null && !numberE164.equals(normalizedNumber)) {
2657892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, numberE164);
2658892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        phoneValues.put(PhoneLookupColumns.MIN_MATCH,
2659892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                                PhoneNumberUtils.toCallerIDMinMatch(numberE164));
2660892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        db.insert(Tables.PHONE_LOOKUP, null, phoneValues);
2661892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    }
2662892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                }
2663892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
2664892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        } finally {
2665892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            cursor.close();
2666892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
2667892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    }
2668892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
26692530512f639c4979fd7371c7dd25dd67e8118124Bai Tao    private void upgradeToVersion406(SQLiteDatabase db) {
26702530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        db.execSQL("ALTER TABLE calls ADD countryiso TEXT;");
26712530512f639c4979fd7371c7dd25dd67e8118124Bai Tao    }
26722530512f639c4979fd7371c7dd25dd67e8118124Bai Tao
2673385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    /**
2674385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     * Adding the DEFAULT_DIRECTORY table.
2675385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     */
2676385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    private void upgradeToVersion408(SQLiteDatabase db) {
2677385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DEFAULT_DIRECTORY + " (" +
2678385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
2679385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        ");");
2680385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2681385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // Process contacts without an account
2682385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
2683385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " SELECT " + RawContacts.CONTACT_ID +
2684385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS +
2685385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL " +
2686385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL ");
2687385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2688385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // Process accounts that don't have a default group (e.g. Exchange)
2689385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
2690385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " SELECT " + RawContacts.CONTACT_ID +
2691385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS +
2692385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE NOT EXISTS" +
2693385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " (SELECT " + Groups._ID +
2694385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "  FROM " + Tables.GROUPS +
2695385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
2696385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_NAME +
2697385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "    AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
2698385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
2699385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "    AND " + Groups.AUTO_ADD + " != 0" +
2700385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ")");
2701385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2702385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        long mimetype = lookupMimeTypeId(db, GroupMembership.CONTENT_ITEM_TYPE);
2703385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2704385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // Process accounts that do have a default group (e.g. Exchange)
2705385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
2706385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " SELECT " + RawContacts.CONTACT_ID +
2707385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS +
2708385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " JOIN " + Tables.DATA +
2709385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "   ON (" + RawContactsColumns.CONCRETE_ID + "=" + Data.RAW_CONTACT_ID + ")" +
2710385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " JOIN " + Tables.GROUPS +
2711385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "   ON (" + GroupMembership.GROUP_ROW_ID + "=" + GroupsColumns.CONCRETE_ID + ")" +
2712385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE " + DataColumns.MIMETYPE_ID + "=" + mimetype +
2713385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "   AND " + Groups.AUTO_ADD + " != 0;");
2714385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    }
2715385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
27163d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    private void upgradeToVersion409(SQLiteDatabase db) {
27173d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
27183d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        createDirectoriesTable(db);
27193d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
2720385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2721b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    public String extractHandleFromEmailAddress(String email) {
2722b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email);
2723b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (tokens.length == 0) {
2724b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return null;
2725b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2726b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2727b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        String address = tokens[0].getAddress();
2728b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        int at = address.indexOf('@');
2729b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (at != -1) {
2730b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return address.substring(0, at);
2731b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2732b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        return null;
2733b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2734b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
273508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov    public String extractAddressFromEmailAddress(String email) {
273608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email);
273708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        if (tokens.length == 0) {
273808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            return null;
273908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        }
274008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
274108768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        return tokens[0].getAddress();
274208768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov    }
274308768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
2744b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private long lookupMimeTypeId(SQLiteDatabase db, String mimeType) {
2745b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2746b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return DatabaseUtils.longForQuery(db,
2747b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    "SELECT " + MimetypesColumns._ID +
2748b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    " FROM " + Tables.MIMETYPES +
2749b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    " WHERE " + MimetypesColumns.MIMETYPE
2750b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                            + "='" + mimeType + "'", null);
2751b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } catch (SQLiteDoneException e) {
2752b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            // No rows of this type in the database
2753b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return -1;
2754b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2755b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2756b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
27575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void bindString(SQLiteStatement stmt, int index, String value) {
27585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (value == null) {
27595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            stmt.bindNull(index);
27605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } else {
27615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            stmt.bindString(index, value);
27625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
27635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
27645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
2765a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    /**
2766f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * Adds index stats into the SQLite database to force it to always use the lookup indexes.
2767f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     */
2768f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    private void updateSqliteStats(SQLiteDatabase db) {
2769f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2770f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        // Specific stats strings are based on an actual large database after running ANALYZE
2771f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        try {
27728fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.CONTACTS,
27738fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "contacts_restricted_index", "10000 9000");
27748fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.CONTACTS,
27758fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "contacts_has_phone_index", "10000 500");
27768fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
27778fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.RAW_CONTACTS,
27788fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "raw_contacts_source_id_index", "10000 1 1 1");
27798fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.RAW_CONTACTS,
27808fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "raw_contacts_contact_id_index", "10000 2");
27818fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
27828fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
27838fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "name_lookup_raw_contact_id_index", "10000 3");
27848fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
2785916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                    "name_lookup_index", "10000 3 2 2 1");
27868fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
27878fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "sqlite_autoindex_name_lookup_1", "10000 3 2 1");
27888fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
27898fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.PHONE_LOOKUP,
27908fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "phone_lookup_index", "10000 2 2 1");
279136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            updateIndexStats(db, Tables.PHONE_LOOKUP,
279236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    "phone_lookup_min_match_index", "10000 2 2 1");
27938fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
27948fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.DATA,
27958fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "data_mimetype_data1_index", "60000 5000 2");
27968fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.DATA,
27978fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "data_raw_contact_id", "60000 10");
27988fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
27998fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.GROUPS,
28008fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "groups_source_id_index", "50 1 1 1");
28018fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
28028fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NICKNAME_LOOKUP,
28038fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "sqlite_autoindex_name_lookup_1", "500 2 1");
28048fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
2805f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        } catch (SQLException e) {
2806f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            Log.e(TAG, "Could not update index stats", e);
2807f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        }
2808f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2809f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2810f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    /**
2811f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * Stores statistics for a given index.
2812f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     *
2813f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * @param stats has the following structure: the first index is the expected size of
2814f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * the table.  The following integer(s) are the expected number of records selected with the
2815f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * index.  There should be one integer per indexed column.
2816f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     */
28175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void updateIndexStats(SQLiteDatabase db, String table, String index,
28185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String stats) {
2819f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        db.execSQL("DELETE FROM sqlite_stat1 WHERE tbl='" + table + "' AND idx='" + index + "';");
2820f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        db.execSQL("INSERT INTO sqlite_stat1 (tbl,idx,stat)"
2821f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                + " VALUES ('" + table + "','" + index + "','" + stats + "');");
2822f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2823f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2824f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    @Override
2825f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    public synchronized SQLiteDatabase getWritableDatabase() {
2826f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        SQLiteDatabase db = super.getWritableDatabase();
2827f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        if (mReopenDatabase) {
2828f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            mReopenDatabase = false;
2829f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            close();
2830f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            db = super.getWritableDatabase();
2831f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        }
2832f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        return db;
2833f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2834f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2835f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    /**
2836a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov     * Wipes all data except mime type and package lookup tables.
2837a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov     */
2838a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    public void wipeData() {
2839a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
28403d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov
284133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.ACCOUNTS + ";");
284269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " VALUES(NULL, NULL)");
284333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov
2844d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CONTACTS + ";");
28455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.RAW_CONTACTS + ";");
2846a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.DATA + ";");
2847a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.PHONE_LOOKUP + ";");
2848a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NAME_LOOKUP + ";");
2849ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("DELETE FROM " + Tables.GROUPS + ";");
2850b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.AGGREGATION_EXCEPTIONS + ";");
2851eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        db.execSQL("DELETE FROM " + Tables.SETTINGS + ";");
2852a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.ACTIVITIES + ";");
28533d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CALLS + ";");
285472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.DIRECTORIES + ";");
285572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov
285672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov        insertDefaultDirectory(db);
285772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov        insertLocalInvisibleDirectory(db);
2858b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
2859b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        // Note: we are not removing reference data from Tables.NICKNAME_LOOKUP
2860a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
2861b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
286204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    public NameSplitter createNameSplitter() {
286304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        return new NameSplitter(
286404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_prefixes),
286504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_last_name_prefixes),
286604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_suffixes),
286704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_conjunctions),
286804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Locale.getDefault());
286904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
287004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
2871b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
2872619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey     * Return the {@link ApplicationInfo#uid} for the given package name.
2873619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey     */
2874619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    public static int getUidForPackageName(PackageManager pm, String packageName) {
2875619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        try {
2876619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            ApplicationInfo clientInfo = pm.getApplicationInfo(packageName, 0 /* no flags */);
2877619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            return clientInfo.uid;
2878619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        } catch (NameNotFoundException e) {
2879619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            throw new RuntimeException(e);
2880619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        }
2881619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
2882619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
2883619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    /**
2884b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Perform an internal string-to-integer lookup using the compiled
2885b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * {@link SQLiteStatement} provided, using the in-memory cache to speed up
2886b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups. If a mapping isn't found in cache or database, it will be
2887b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * created. All new, uncached answers are added to the cache automatically.
2888b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *
2889b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param query Compiled statement used to query for the mapping.
2890b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param insert Compiled statement used to insert a new mapping when no
2891b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *            existing one is found in cache or from query.
2892b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param value Value to find mapping for.
2893b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param cache In-memory cache of previous answers.
2894b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @return An unique integer mapping for the given value.
2895b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
2896f4a3b7e523e36679b68edd2af632e26648758ff2Dmitri Plotnikov    private long getCachedId(SQLiteStatement query, SQLiteStatement insert,
2897b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String value, HashMap<String, Long> cache) {
2898b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Try an in-memory cache lookup
2899b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (cache.containsKey(value)) {
2900b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return cache.get(value);
2901b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
2902b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
2903b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        long id = -1;
2904b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
2905b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try searching database for mapping
2906b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(query, 1, value);
2907b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            id = query.simpleQueryForLong();
2908b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
2909b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Nothing found, so try inserting new mapping
2910b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(insert, 1, value);
2911b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            id = insert.executeInsert();
2912b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
2913b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
2914b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (id != -1) {
2915b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Cache and return the new answer
2916b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            cache.put(value, id);
2917b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return id;
2918b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } else {
2919b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Otherwise throw if no mapping found or created
2920b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            throw new IllegalStateException("Couldn't find or create internal "
2921b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                    + "lookup table entry for value " + value);
2922b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
2923b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
2924b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
2925b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
2926ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Convert a package name into an integer, using {@link Tables#PACKAGES} for
2927b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
2928b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
2929b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getPackageId(String packageName) {
2930b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
2931b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
2932b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return getCachedId(mPackageQuery, mPackageInsert, packageName, mPackageCache);
2933b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
2934b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
2935b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
2936ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Convert a mimetype into an integer, using {@link Tables#MIMETYPES} for
2937b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
2938b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
2939b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getMimeTypeId(String mimetype) {
2940b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
2941b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
29425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        return getMimeTypeIdNoDbCheck(mimetype);
29435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
29445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
29455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private long getMimeTypeIdNoDbCheck(String mimetype) {
2946b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return getCachedId(mMimetypeQuery, mMimetypeInsert, mimetype, mMimetypeCache);
2947b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
2948b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
2949b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
2950ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Find the mimetype for the given {@link Data#_ID}.
2951b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
2952b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getDataMimeType(long dataId) {
2953b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
2954b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
2955b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
2956b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
2957b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mDataMimetypeQuery, 1, dataId);
2958b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mDataMimetypeQuery.simpleQueryForString();
2959b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
2960b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
2961b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
2962b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
2963b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
2964b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
2965b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
2966b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
2967b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Find the mime-type for the given {@link Activities#_ID}.
2968b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
2969b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getActivityMimeType(long activityId) {
2970b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
2971b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
2972b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
2973b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
2974b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mActivitiesMimetypeQuery, 1, activityId);
2975b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mActivitiesMimetypeQuery.simpleQueryForString();
2976b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
2977b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
2978b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
2979b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
2980b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
2981b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
29826bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov
29836bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov    /**
2984d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Update {@link Contacts#IN_VISIBLE_GROUP} for all contacts.
2985ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     */
2986ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public void updateAllVisible() {
2987385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        updateCustomContactVisibility(getWritableDatabase(), "");
2988ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
2989ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
2990ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    /**
2991385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     * Update {@link Contacts#IN_VISIBLE_GROUP} and
2992385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     * {@link Tables#DEFAULT_DIRECTORY} for a specific contact.
2993ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     */
2994fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov    public void updateContactVisible(long contactId) {
29954394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
2996385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        updateCustomContactVisibility(getWritableDatabase(),
2997385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " AND " + Contacts._ID + "=" + contactId);
2998385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2999385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        String contactIdAsString = String.valueOf(contactId);
3000385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        long mimetype = getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
3001385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3002385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // The contact will be included in the default directory if contains
3003385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // a raw contact that is in an AUTO_ADD group or in an account that
3004385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // does not have any AUTO_ADD groups.
3005385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        long visibleRawContact = DatabaseUtils.longForQuery(db,
3006385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "SELECT EXISTS (" +
3007385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts.CONTACT_ID +
3008385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3009385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " JOIN " + Tables.DATA +
3010385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   ON (" + RawContactsColumns.CONCRETE_ID + "="
3011385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                            + Data.RAW_CONTACT_ID + ")" +
3012385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " JOIN " + Tables.GROUPS +
3013385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   ON (" + GroupMembership.GROUP_ROW_ID + "="
3014385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                            + GroupsColumns.CONCRETE_ID + ")" +
3015385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3016385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + DataColumns.MIMETYPE_ID + "=?" +
3017385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + Groups.AUTO_ADD + " != 0" +
3018385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ") OR EXISTS (" +
3019385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts._ID +
3020385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3021385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3022385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND NOT EXISTS" +
3023385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        " (SELECT " + Groups._ID +
3024385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  FROM " + Tables.GROUPS +
3025385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
3026385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                                + GroupsColumns.CONCRETE_ACCOUNT_NAME +
3027385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
3028385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                                + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
3029385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  AND " + Groups.AUTO_ADD + " != 0" +
3030385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        ")" +
3031385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ") OR EXISTS (" +
3032385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts._ID +
3033385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3034385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3035385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL " +
3036385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL" +
3037385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ")",
3038385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                new String[] {
3039385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    contactIdAsString,
30406c47e208236a62c55f396116e087331e05e148f3Dmitri Plotnikov                    String.valueOf(mimetype),
3041385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    contactIdAsString,
30426c47e208236a62c55f396116e087331e05e148f3Dmitri Plotnikov                    contactIdAsString
3043385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                });
3044385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3045385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        if (visibleRawContact != 0) {
3046385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY + " VALUES(?)",
3047385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    new String[] { contactIdAsString });
3048385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        } else {
3049385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            db.execSQL("DELETE FROM " + Tables.DEFAULT_DIRECTORY + " WHERE " + Contacts._ID + "=?",
3050385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    new String[] { contactIdAsString });
3051385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        }
3052385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    }
30534394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
3054385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    private void updateCustomContactVisibility(SQLiteDatabase db, String selection) {
3055ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        final long groupMembershipMimetypeId = getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
30564394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        String[] selectionArgs = new String[]{String.valueOf(groupMembershipMimetypeId)};
30574394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
30584394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // First delete what needs to be deleted, then insert what needs to be added.
30594394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // Since flash writes are very expensive, this approach is much better than
30604394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // delete-all-insert-all.
30614394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.VISIBLE_CONTACTS +
30624394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " WHERE " + "_id NOT IN" +
30634394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        "(SELECT " + Contacts._ID +
30644394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        " FROM " + Tables.CONTACTS +
30654394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        " WHERE (" + Clauses.CONTACT_IS_VISIBLE + ")=1) " + selection,
30664394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                selectionArgs);
3067fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
30684394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.VISIBLE_CONTACTS +
30694394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " SELECT " + Contacts._ID +
30704394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " FROM " + Tables.CONTACTS +
30714394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " WHERE " + Contacts._ID +
30724394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " NOT IN " + Tables.VISIBLE_CONTACTS +
30734394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                           " AND (" + Clauses.CONTACT_IS_VISIBLE + ")=1 " + selection,
30744394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                selectionArgs);
3075ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
3076ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
3077ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    /**
3078d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Returns contact ID for the given contact or zero if it is NULL.
30796bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov     */
3080d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    public long getContactId(long rawContactId) {
30816bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        getReadableDatabase();
30826bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        try {
3083d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov            DatabaseUtils.bindObjectToProgram(mContactIdQuery, 1, rawContactId);
3084d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov            return mContactIdQuery.simpleQueryForLong();
30856bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        } catch (SQLiteDoneException e) {
3086a3bd0246ca3741877488bca7aadd91c79b2fd8d2Fred Quintana            // No valid mapping found, so return 0
30876bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov            return 0;
30886bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        }
30896bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov    }
309061bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov
30915ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov    public int getAggregationMode(long rawContactId) {
3092f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        getReadableDatabase();
3093f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        try {
30945ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov            DatabaseUtils.bindObjectToProgram(mAggregationModeQuery, 1, rawContactId);
3095f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            return (int)mAggregationModeQuery.simpleQueryForLong();
3096f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        } catch (SQLiteDoneException e) {
30976cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov            // No valid row found, so return "disabled"
30986cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov            return RawContacts.AGGREGATION_MODE_DISABLED;
3099f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3100f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3101f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
3102892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    public void buildPhoneLookupAndContactQuery(
3103892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            SQLiteQueryBuilder qb, String normalizedNumber, String numberE164) {
3104892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        String minMatch = PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber);
3105e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        StringBuilder sb = new StringBuilder();
310636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        appendPhoneLookupTables(sb, minMatch, true);
3107e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        qb.setTables(sb.toString());
3108e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
3109e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb = new StringBuilder();
3110892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        appendPhoneLookupSelection(sb, normalizedNumber, numberE164);
3111e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        qb.appendWhere(sb.toString());
3112bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    }
3113bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
3114e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    public String buildPhoneLookupAsNestedQuery(String number) {
3115e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        StringBuilder sb = new StringBuilder();
311636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        final String minMatch = PhoneNumberUtils.toCallerIDMinMatch(number);
3117e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append("(SELECT DISTINCT raw_contact_id" + " FROM ");
311836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        appendPhoneLookupTables(sb, minMatch, false);
3119e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(" WHERE ");
3120892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        appendPhoneLookupSelection(sb, number, null);
3121e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(")");
3122e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        return sb.toString();
3123e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    }
3124e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
312536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    private void appendPhoneLookupTables(StringBuilder sb, final String minMatch,
3126e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov            boolean joinContacts) {
3127e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(Tables.RAW_CONTACTS);
3128e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        if (joinContacts) {
3129fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov            sb.append(" JOIN " + getContactView() + " contacts_view"
3130fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                    + " ON (contacts_view._id = raw_contacts.contact_id)");
3131e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        }
3132892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        sb.append(", (SELECT data_id, normalized_number, length(normalized_number) as len "
3133892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " FROM phone_lookup " + " WHERE (" + Tables.PHONE_LOOKUP + "."
3134892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + PhoneLookupColumns.MIN_MATCH + " = '");
313536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        sb.append(minMatch);
313636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        sb.append("')) AS lookup, " + Tables.DATA);
3137e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    }
3138e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
3139892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    private void appendPhoneLookupSelection(StringBuilder sb, String number, String numberE164) {
3140892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        sb.append("lookup.data_id=data._id AND data.raw_contact_id=raw_contacts._id");
3141892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        boolean hasNumberE164 = !TextUtils.isEmpty(numberE164);
3142892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        boolean hasNumber = !TextUtils.isEmpty(number);
3143892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (hasNumberE164 || hasNumber) {
3144892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            sb.append(" AND ( ");
3145892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumberE164) {
3146892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" lookup.normalized_number = ");
3147892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                DatabaseUtils.appendEscapedSQLString(sb, numberE164);
3148892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3149892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumberE164 && hasNumber) {
3150892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" OR ");
3151892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3152892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumber) {
3153892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                int numberLen = number.length();
3154892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" lookup.len <= ");
3155892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(numberLen);
3156892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" AND substr(");
3157892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                DatabaseUtils.appendEscapedSQLString(sb, number);
3158892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(',');
3159892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(numberLen);
3160892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" - lookup.len + 1) = lookup.normalized_number");
3161892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3162892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            sb.append(')');
3163892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
316436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    }
316536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
316636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    public String getUseStrictPhoneNumberComparisonParameter() {
316736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        return mUseStrictPhoneNumberComparison ? "1" : "0";
3168fb362d1a5df250a49fad06db323b0d41fe0e3757Dmitri Plotnikov    }
3169bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
3170619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    /**
3171b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     * Loads common nickname mappings into the database.
3172b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     */
3173b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private void loadNicknameLookupTable(SQLiteDatabase db) {
317451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NICKNAME_LOOKUP);
317551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
317628f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar        String[] strings = mContext.getResources().getStringArray(
317728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar                com.android.internal.R.array.common_nicknames);
3178b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        if (strings == null || strings.length == 0) {
3179b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            return;
3180b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
3181b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
3182b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        SQLiteStatement nicknameLookupInsert = db.compileStatement("INSERT INTO "
3183b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                + Tables.NICKNAME_LOOKUP + "(" + NicknameLookupColumns.NAME + ","
3184b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                + NicknameLookupColumns.CLUSTER + ") VALUES (?,?)");
3185b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
318651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
318751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            for (int clusterId = 0; clusterId < strings.length; clusterId++) {
318851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                String[] names = strings[clusterId].split(",");
318951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                for (int j = 0; j < names.length; j++) {
319051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    String name = NameNormalizer.normalize(names[j]);
319151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    try {
319251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        DatabaseUtils.bindObjectToProgram(nicknameLookupInsert, 1, name);
319351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        DatabaseUtils.bindObjectToProgram(nicknameLookupInsert, 2,
319451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                                String.valueOf(clusterId));
319551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        nicknameLookupInsert.executeInsert();
319651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    } catch (SQLiteException e) {
319751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
319851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        // Print the exception and keep going - this is not a fatal error
319951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        Log.e(TAG, "Cannot insert nickname: " + names[j], e);
320051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    }
3201b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                }
3202b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            }
320351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
320451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            nicknameLookupInsert.close();
3205b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
3206b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    }
3207b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
3208f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    public static void copyStringValue(ContentValues toValues, String toKey,
3209f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            ContentValues fromValues, String fromKey) {
3210f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        if (fromValues.containsKey(fromKey)) {
3211f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            toValues.put(toKey, fromValues.getAsString(fromKey));
3212f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3213f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3214f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
3215f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    public static void copyLongValue(ContentValues toValues, String toKey,
3216f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            ContentValues fromValues, String fromKey) {
3217f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        if (fromValues.containsKey(fromKey)) {
3218f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            long longValue;
3219f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            Object value = fromValues.get(fromKey);
3220f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            if (value instanceof Boolean) {
3221f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                if ((Boolean)value) {
3222f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                    longValue = 1;
3223f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                } else {
3224f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                    longValue = 0;
3225f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                }
32261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov            } else if (value instanceof String) {
32271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov                longValue = Long.parseLong((String)value);
3228f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            } else {
32291b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov                longValue = ((Number)value).longValue();
3230f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            }
3231f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            toValues.put(toKey, longValue);
3232f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3233f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3234f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
323535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    public SyncStateContentProviderHelper getSyncState() {
323635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        return mSyncState;
323735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    }
3238c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3239c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    /**
3240c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     * Delete the aggregate contact if it has no constituent raw contacts other
3241c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     * than the supplied one.
3242c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     */
3243c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    public void removeContactIfSingleton(long rawContactId) {
3244c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
3245c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3246c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        // Obtain contact ID from the supplied raw contact ID
3247c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        String contactIdFromRawContactId = "(SELECT " + RawContacts.CONTACT_ID + " FROM "
3248c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=" + rawContactId + ")";
3249c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3250c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        // Find other raw contacts in the same aggregate contact
3251c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        String otherRawContacts = "(SELECT contacts1." + RawContacts._ID + " FROM "
3252c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + Tables.RAW_CONTACTS + " contacts1 JOIN " + Tables.RAW_CONTACTS + " contacts2 ON ("
3253c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "contacts1." + RawContacts.CONTACT_ID + "=contacts2." + RawContacts.CONTACT_ID
3254c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + ") WHERE contacts1." + RawContacts._ID + "!=" + rawContactId + ""
3255c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " AND contacts2." + RawContacts._ID + "=" + rawContactId + ")";
3256c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3257c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CONTACTS
3258c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " WHERE " + Contacts._ID + "=" + contactIdFromRawContactId
3259c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " AND NOT EXISTS " + otherRawContacts + ";");
3260c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    }
32614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
32624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    /**
3263b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     * Returns the value from the {@link Tables#PROPERTIES} table.
3264b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     */
3265b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public String getProperty(String key, String defaultValue) {
3266b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        Cursor cursor = getReadableDatabase().query(Tables.PROPERTIES,
3267b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                new String[]{PropertiesColumns.PROPERTY_VALUE},
3268b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_KEY + "=?",
3269b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                new String[]{key}, null, null, null);
3270b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        String value = null;
3271b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        try {
3272b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            if (cursor.moveToFirst()) {
3273b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                value = cursor.getString(0);
3274b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            }
3275b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        } finally {
3276b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            cursor.close();
3277b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        }
3278b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3279b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        return value != null ? value : defaultValue;
3280b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
3281b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3282b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    /**
3283b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     * Stores a key-value pair in the {@link Tables#PROPERTIES} table.
3284b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     */
3285b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public void setProperty(String key, String value) {
32863d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        setProperty(getWritableDatabase(), key, value);
32873d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
32883d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
32893d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    private void setProperty(SQLiteDatabase db, String key, String value) {
3290b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ContentValues values = new ContentValues();
3291b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        values.put(PropertiesColumns.PROPERTY_KEY, key);
3292b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        values.put(PropertiesColumns.PROPERTY_VALUE, value);
32933d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        db.replace(Tables.PROPERTIES, null, values);
3294b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
3295b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3296b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    /**
32974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     * Check if {@link Binder#getCallingUid()} should be allowed access to
32984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     * {@link RawContacts#IS_RESTRICTED} data.
32994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     */
3300d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    boolean hasAccessToRestrictedData() {
33014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        final PackageManager pm = mContext.getPackageManager();
33026ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        int caller = Binder.getCallingUid();
33036ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        if (caller == 0) return true; // root can do anything
33046ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        final String[] callerPackages = pm.getPackagesForUid(caller);
33054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
33064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        // Has restricted access if caller matches any packages
33074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        for (String callerPackage : callerPackages) {
3308d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton            if (hasAccessToRestrictedData(callerPackage)) {
3309763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                return true;
3310763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar            }
3311763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        }
3312763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return false;
3313763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    }
3314763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar
3315763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    /**
3316763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     * Check if requestingPackage should be allowed access to
3317763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     * {@link RawContacts#IS_RESTRICTED} data.
3318763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     */
3319d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    boolean hasAccessToRestrictedData(String requestingPackage) {
3320d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        if (mUnrestrictedPackages != null) {
3321d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton            for (String allowedPackage : mUnrestrictedPackages) {
3322d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                if (allowedPackage.equals(requestingPackage)) {
3323d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                    return true;
3324d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                }
33254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov            }
33264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        }
33274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        return false;
33284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
33294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
33304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getDataView() {
3331d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa        return getDataView(false);
3332d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3333d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3334d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    public String getDataView(boolean requireRestrictedView) {
3335d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3336d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa                Views.DATA_ALL : Views.DATA_RESTRICTED;
33374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
33384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
33394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getRawContactView() {
3340763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return getRawContactView(false);
3341763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    }
3342763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar
3343763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    public String getRawContactView(boolean requireRestrictedView) {
3344d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3345763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                Views.RAW_CONTACTS_ALL : Views.RAW_CONTACTS_RESTRICTED;
33464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
33474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
33484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getContactView() {
3349763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return getContactView(false);
33504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
33514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
3352763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    public String getContactView(boolean requireRestrictedView) {
3353d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3354763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                Views.CONTACTS_ALL : Views.CONTACTS_RESTRICTED;
3355f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey    }
3356f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey
335789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov    public String getGroupView() {
335889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        return Views.GROUPS_ALL;
335989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov    }
336089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
3361a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getRawEntitiesView() {
3362a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return getRawEntitiesView(false);
3363a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    }
3364a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
3365a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getRawEntitiesView(boolean requireRestrictedView) {
3366a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3367a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                Views.RAW_ENTITIES : Views.RAW_ENTITIES_RESTRICTED;
3368a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    }
3369a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
3370a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getEntitiesView() {
3371a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return getEntitiesView(false);
3372d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3373d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3374a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getEntitiesView(boolean requireRestrictedView) {
3375d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3376a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                Views.ENTITIES : Views.ENTITIES_RESTRICTED;
3377d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3378d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3379ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov    /**
3380ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov     * Test if any of the columns appear in the given projection.
3381ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov     */
3382ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov    public boolean isInProjection(String[] projection, String... columns) {
338382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        if (projection == null) {
338482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            return true;
338582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        }
3386ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov
338782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        // Optimized for a single-column test
338882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        if (columns.length == 1) {
338982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            String column = columns[0];
339082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            for (String test : projection) {
339182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                if (column.equals(test)) {
339282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                    return true;
339382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                }
339482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            }
339582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        } else {
339682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            for (String test : projection) {
339782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                for (String column : columns) {
3398ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                    if (column.equals(test)) {
3399ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                        return true;
3400ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                    }
3401ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                }
3402ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov            }
3403ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov        }
3404ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov        return false;
34054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
3406fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3407fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    /**
3408fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * Returns a detailed exception message for the supplied URI.  It includes the calling
3409fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * user and calling package(s).
3410fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     */
3411fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    public String exceptionMessage(Uri uri) {
3412fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        return exceptionMessage(null, uri);
3413fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    }
3414fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3415fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    /**
3416fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * Returns a detailed exception message for the supplied URI.  It includes the calling
3417fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * user and calling package(s).
3418fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     */
3419fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    public String exceptionMessage(String message, Uri uri) {
3420fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        StringBuilder sb = new StringBuilder();
3421fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (message != null) {
3422fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(message).append("; ");
3423fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3424fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        sb.append("URI: ").append(uri);
3425fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        final PackageManager pm = mContext.getPackageManager();
3426fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        int callingUid = Binder.getCallingUid();
3427fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        sb.append(", calling user: ");
3428fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        String userName = pm.getNameForUid(callingUid);
3429fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (userName != null) {
3430fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(userName);
3431fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        } else {
3432fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(callingUid);
3433fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3434fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3435fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        final String[] callerPackages = pm.getPackagesForUid(callingUid);
3436fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (callerPackages != null && callerPackages.length > 0) {
3437fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            if (callerPackages.length == 1) {
3438fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(", calling package:");
3439fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(callerPackages[0]);
3440fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            } else {
3441fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(", calling package is one of: [");
3442fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                for (int i = 0; i < callerPackages.length; i++) {
3443fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    if (i != 0) {
3444fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                        sb.append(", ");
3445fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    }
3446fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    sb.append(callerPackages[i]);
3447fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                }
3448fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append("]");
3449fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            }
3450fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3451fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3452fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        return sb.toString();
3453fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    }
3454892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
3455892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    protected String getCountryIso() {
3456892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        CountryDetector detector =
3457892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            (CountryDetector) mContext.getSystemService(Context.COUNTRY_DETECTOR);
3458892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        return detector.detectCountry().getCountryIso();
3459892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    }
3460b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey}
3461