ContactsDatabaseHelper.java revision 3ea7932a47027c8629d3a301e1a16e7d2c8a298d
1b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey/*
2b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Copyright (C) 2009 The Android Open Source Project
3b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
4b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * you may not use this file except in compliance with the License.
6b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * You may obtain a copy of the License at
7b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
8b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
10b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Unless required by applicable law or agreed to in writing, software
11b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * See the License for the specific language governing permissions and
14b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * limitations under the License
15b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey */
16b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarpackage com.android.providers.contacts;
18b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1953214b3ed12b0ff9cb589b6559311f2ac142f2e3Bjorn Bringertimport com.android.common.content.SyncStateContentProviderHelper;
2067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
2182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.content.ContentResolver;
22619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.ContentValues;
23b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.content.Context;
24619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.ApplicationInfo;
25619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.PackageManager;
26619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
27d91272b48f97243533c6580981e12a4847b5783fJeff Hamiltonimport android.content.res.Resources;
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     */
91c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov    static final int DATABASE_VERSION = 415;
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
479e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    public static final class DirectoryColumns {
480e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov        public static final String TYPE_RESOURCE_NAME = "typeResourceName";
481e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    }
482e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov
4833296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey    /** In-memory cache of previously found MIME-type mappings */
484bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    private final HashMap<String, Long> mMimetypeCache = new HashMap<String, Long>();
485b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** In-memory cache of previously found package name mappings */
486bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    private final HashMap<String, Long> mPackageCache = new HashMap<String, Long>();
487b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
488b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
489b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** Compiled statements for querying and inserting mappings */
490b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mMimetypeQuery;
491b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mPackageQuery;
492d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    private SQLiteStatement mContactIdQuery;
493f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    private SQLiteStatement mAggregationModeQuery;
494b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mMimetypeInsert;
495b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mPackageInsert;
496b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mDataMimetypeQuery;
497b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mActivitiesMimetypeQuery;
498b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
499b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private final Context mContext;
50035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    private final SyncStateContentProviderHelper mSyncState;
501f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov
502f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    private boolean mReopenDatabase = false;
503f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
504b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    private static ContactsDatabaseHelper sSingleton = null;
505b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
50636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    private boolean mUseStrictPhoneNumberComparison;
5073a6a49cfb06272e3e25f3c390a9cf4002da6e34dDaisuke Miyakawa
508d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    /**
509d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton     * List of package names with access to {@link RawContacts#IS_RESTRICTED} data.
510d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton     */
511d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    private String[] mUnrestrictedPackages;
512d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton
513b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    public static synchronized ContactsDatabaseHelper getInstance(Context context) {
514b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (sSingleton == null) {
515b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov            sSingleton = new ContactsDatabaseHelper(context);
516b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
517b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return sSingleton;
518b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
519b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
5201f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    /**
52131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov     * Private constructor, callers except unit tests should obtain an instance through
52235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana     * {@link #getInstance(android.content.Context)} instead.
5231f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey     */
524b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    ContactsDatabaseHelper(Context context) {
525b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        super(context, DATABASE_NAME, null, DATABASE_VERSION);
526d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        Resources resources = context.getResources();
527619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
528b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        mContext = context;
52928b3769e3fcecae56c3fc70cbcb0f95282b9640eFred Quintana        mSyncState = new SyncStateContentProviderHelper();
53036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        mUseStrictPhoneNumberComparison =
531d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                resources.getBoolean(
532d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                        com.android.internal.R.bool.config_use_strict_phone_number_comparation);
5330f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        int resourceId = resources.getIdentifier("unrestricted_packages", "array",
5340f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov                context.getPackageName());
5350f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        if (resourceId != 0) {
5360f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov            mUnrestrictedPackages = resources.getStringArray(resourceId);
5370f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        } else {
5380f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov            mUnrestrictedPackages = new String[0];
5390f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        }
540b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
541b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
542b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
543b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onOpen(SQLiteDatabase db) {
54435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        mSyncState.onDatabaseOpened(db);
54535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
546b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Create compiled statements for package and mimetype lookups
547ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mMimetypeQuery = db.compileStatement("SELECT " + MimetypesColumns._ID + " FROM "
548ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + Tables.MIMETYPES + " WHERE " + MimetypesColumns.MIMETYPE + "=?");
549ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mPackageQuery = db.compileStatement("SELECT " + PackagesColumns._ID + " FROM "
550ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + Tables.PACKAGES + " WHERE " + PackagesColumns.PACKAGE + "=?");
551d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        mContactIdQuery = db.compileStatement("SELECT " + RawContacts.CONTACT_ID + " FROM "
5525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?");
5536cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov        mAggregationModeQuery = db.compileStatement("SELECT " + RawContacts.AGGREGATION_MODE
5545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?");
555ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mMimetypeInsert = db.compileStatement("INSERT INTO " + Tables.MIMETYPES + "("
556ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + MimetypesColumns.MIMETYPE + ") VALUES (?)");
557ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mPackageInsert = db.compileStatement("INSERT INTO " + Tables.PACKAGES + "("
558ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + PackagesColumns.PACKAGE + ") VALUES (?)");
559ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
560ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mDataMimetypeQuery = db.compileStatement("SELECT " + MimetypesColumns.MIMETYPE + " FROM "
561ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + Tables.DATA_JOIN_MIMETYPES + " WHERE " + Tables.DATA + "." + Data._ID + "=?");
562ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mActivitiesMimetypeQuery = db.compileStatement("SELECT " + MimetypesColumns.MIMETYPE
563ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + " FROM " + Tables.ACTIVITIES_JOIN_MIMETYPES + " WHERE " + Tables.ACTIVITIES + "."
564b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + Activities._ID + "=?");
5651f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
5661f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        db.execSQL("ATTACH DATABASE ':memory:' AS " + DATABASE_PRESENCE + ";");
567e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS " + DATABASE_PRESENCE + "." + Tables.PRESENCE + " ("+
56882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.DATA_ID + " INTEGER PRIMARY KEY REFERENCES data(_id)," +
56982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.PROTOCOL + " INTEGER NOT NULL," +
57082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.CUSTOM_PROTOCOL + " TEXT," +
57182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.IM_HANDLE + " TEXT," +
57282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.IM_ACCOUNT + " TEXT," +
573a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                PresenceColumns.CONTACT_ID + " INTEGER REFERENCES contacts(_id)," +
574a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                PresenceColumns.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
57582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.PRESENCE + " INTEGER," +
576aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                StatusUpdates.CHAT_CAPABILITY + " INTEGER NOT NULL DEFAULT 0," +
57782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                "UNIQUE(" + StatusUpdates.PROTOCOL + ", " + StatusUpdates.CUSTOM_PROTOCOL
57882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                    + ", " + StatusUpdates.IM_HANDLE + ", " + StatusUpdates.IM_ACCOUNT + ")" +
5791f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        ");");
5801f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
581e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE INDEX IF NOT EXISTS " + DATABASE_PRESENCE + ".presenceIndex" + " ON "
5824dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov                + Tables.PRESENCE + " (" + PresenceColumns.RAW_CONTACT_ID + ");");
58309562b6c3a420ded0d02b9bd2290de2dbab9e304Vasu Nori        db.execSQL("CREATE INDEX IF NOT EXISTS " + DATABASE_PRESENCE + ".presenceIndex2" + " ON "
58409562b6c3a420ded0d02b9bd2290de2dbab9e304Vasu Nori                + Tables.PRESENCE + " (" + PresenceColumns.CONTACT_ID + ");");
585e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov
586e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS "
587aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + DATABASE_PRESENCE + "." + Tables.AGGREGATED_PRESENCE + " ("+
588e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov                AggregatedPresenceColumns.CONTACT_ID
589e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov                        + " INTEGER PRIMARY KEY REFERENCES contacts(_id)," +
590632248ae0053fa99b1f5b4cfaab3e55b7453fcb1Vasu Nori                StatusUpdates.PRESENCE + " INTEGER," +
591aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                StatusUpdates.CHAT_CAPABILITY + " INTEGER NOT NULL DEFAULT 0" +
592e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        ");");
593bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
594bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
595bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_deleted"
596bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEFORE DELETE ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
597bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
598bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + "   DELETE FROM " + Tables.AGGREGATED_PRESENCE
599bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + "     WHERE " + AggregatedPresenceColumns.CONTACT_ID + " = " +
600bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        "(SELECT " + PresenceColumns.CONTACT_ID +
601bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " FROM " + Tables.PRESENCE +
602bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " WHERE " + PresenceColumns.RAW_CONTACT_ID
603bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                + "=OLD." + PresenceColumns.RAW_CONTACT_ID +
604bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " AND NOT EXISTS" +
605bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                "(SELECT " + PresenceColumns.RAW_CONTACT_ID +
606bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " FROM " + Tables.PRESENCE +
607bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " WHERE " + PresenceColumns.CONTACT_ID
608bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                        + "=OLD." + PresenceColumns.CONTACT_ID +
609bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " AND " + PresenceColumns.RAW_CONTACT_ID
610bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                        + "!=OLD." + PresenceColumns.RAW_CONTACT_ID + "));"
611bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
612bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
613aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori        final String replaceAggregatePresenceSql =
614aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                "INSERT OR REPLACE INTO " + Tables.AGGREGATED_PRESENCE + "("
615093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + AggregatedPresenceColumns.CONTACT_ID + ", "
616093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.PRESENCE + ", "
617093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.CHAT_CAPABILITY + ")"
618093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                + " SELECT "
619093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + PresenceColumns.CONTACT_ID + ","
620093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.PRESENCE + ","
621093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.CHAT_CAPABILITY
622aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " FROM " + Tables.PRESENCE
623aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " WHERE "
624093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + " (ifnull(" + StatusUpdates.PRESENCE + ",0)  * 10 "
625093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                            + "+ ifnull(" + StatusUpdates.CHAT_CAPABILITY + ", 0))"
626093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + " = (SELECT "
627093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + "MAX (ifnull(" + StatusUpdates.PRESENCE + ",0)  * 10 "
628093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                                + "+ ifnull(" + StatusUpdates.CHAT_CAPABILITY + ", 0))"
629093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + " FROM " + Tables.PRESENCE
630093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + " WHERE " + PresenceColumns.CONTACT_ID
631093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                            + "=NEW." + PresenceColumns.CONTACT_ID
632093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + ")"
633093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                + " AND " + PresenceColumns.CONTACT_ID + "=NEW." + PresenceColumns.CONTACT_ID + ";";
634bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
635bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_inserted"
636bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " AFTER INSERT ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
637bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
638bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + replaceAggregatePresenceSql
639bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
640bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
641bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_updated"
642bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " AFTER UPDATE ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
643bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
644bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + replaceAggregatePresenceSql
645bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
646b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
647b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
648b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
649b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onCreate(SQLiteDatabase db) {
650b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        Log.i(TAG, "Bootstrapping database");
651b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
65235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        mSyncState.createDatabase(db);
65335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
654b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // One row per group of contacts corresponding to the same person
655d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.CONTACTS + " (" +
656b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
657fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
658d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.PHOTO_ID + " INTEGER REFERENCES data(_id)," +
659d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.CUSTOM_RINGTONE + " TEXT," +
660d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," +
661d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," +
662d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.LAST_TIME_CONTACTED + " INTEGER," +
663d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.STARRED + " INTEGER NOT NULL DEFAULT 0," +
664f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov                Contacts.HAS_PHONE_NUMBER + " INTEGER NOT NULL DEFAULT 0," +
6655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                Contacts.LOOKUP_KEY + " TEXT," +
666a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                ContactsColumns.LAST_STATUS_UPDATE_ID + " INTEGER REFERENCES data(_id)," +
6674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.SINGLE_IS_RESTRICTED + " INTEGER NOT NULL DEFAULT 0" +
668b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
669b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
67054d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX contacts_has_phone_index ON " + Tables.CONTACTS + " (" +
67154d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                Contacts.HAS_PHONE_NUMBER +
67254d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
67354d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
67454d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX contacts_restricted_index ON " + Tables.CONTACTS + " (" +
67554d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                ContactsColumns.SINGLE_IS_RESTRICTED +
67654d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
67754d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
678fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_name_raw_contact_id_index ON " + Tables.CONTACTS + " (" +
679fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID +
680fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
681fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
682b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Contacts table
6835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.RAW_CONTACTS + " (" +
6846cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
6856cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.IS_RESTRICTED + " INTEGER DEFAULT 0," +
6866cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.ACCOUNT_NAME + " STRING DEFAULT NULL, " +
6876cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + " STRING DEFAULT NULL, " +
6886cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.SOURCE_ID + " TEXT," +
68997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                RawContacts.RAW_CONTACT_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
6906cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.VERSION + " INTEGER NOT NULL DEFAULT 1," +
69173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov                RawContacts.DIRTY + " INTEGER NOT NULL DEFAULT 0," +
69233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov                RawContacts.DELETED + " INTEGER NOT NULL DEFAULT 0," +
69354d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                RawContacts.CONTACT_ID + " INTEGER REFERENCES contacts(_id)," +
6946cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.AGGREGATION_MODE + " INTEGER NOT NULL DEFAULT " +
6956cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                        RawContacts.AGGREGATION_MODE_DEFAULT + "," +
6968e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov                RawContactsColumns.AGGREGATION_NEEDED + " INTEGER NOT NULL DEFAULT 1," +
6976cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.CUSTOM_RINGTONE + " TEXT," +
6986cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," +
6996cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," +
7006cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.LAST_TIME_CONTACTED + " INTEGER," +
70133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov                RawContacts.STARRED + " INTEGER NOT NULL DEFAULT 0," +
7025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_PRIMARY + " TEXT," +
7035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_ALTERNATIVE + " TEXT," +
7045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_SOURCE + " INTEGER NOT NULL DEFAULT " +
70525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov                        DisplayNameSources.UNDEFINED + "," +
7065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.PHONETIC_NAME + " TEXT," +
7075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.PHONETIC_NAME_STYLE + " TEXT," +
708de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                RawContacts.SORT_KEY_PRIMARY + " TEXT COLLATE " +
709de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                        ContactsProvider2.PHONEBOOK_COLLATOR_NAME + "," +
710de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                RawContacts.SORT_KEY_ALTERNATIVE + " TEXT COLLATE " +
711de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                        ContactsProvider2.PHONEBOOK_COLLATOR_NAME + "," +
712f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                RawContacts.NAME_VERIFIED + " INTEGER NOT NULL DEFAULT 0," +
7133cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC1 + " TEXT, " +
7143cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC2 + " TEXT, " +
7153cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC3 + " TEXT, " +
7163cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC4 + " TEXT " +
717b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
718b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
71954d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contacts_contact_id_index ON " + Tables.RAW_CONTACTS + " (" +
72054d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                RawContacts.CONTACT_ID +
72154d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
72254d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
7235f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contacts_source_id_index ON " + Tables.RAW_CONTACTS + " (" +
7245f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.SOURCE_ID + ", " +
7255f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + ", " +
7265f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.ACCOUNT_NAME +
7275f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        ");");
7285f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov
729f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        // TODO readd the index and investigate a controlled use of it
730f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//        db.execSQL("CREATE INDEX raw_contacts_agg_index ON " + Tables.RAW_CONTACTS + " (" +
731f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//                RawContactsColumns.AGGREGATION_NEEDED +
732f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//        ");");
7338e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov
734b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Package name mapping table
735ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PACKAGES + " (" +
736ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                PackagesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
737ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                PackagesColumns.PACKAGE + " TEXT NOT NULL" +
738b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
739b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
740ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // Mimetype mapping table
741ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.MIMETYPES + " (" +
742ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                MimetypesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
743ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                MimetypesColumns.MIMETYPE + " TEXT NOT NULL" +
744b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
745b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
74608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        // Mimetype table requires an index on mime type
74708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX mime_type ON " + Tables.MIMETYPES + " (" +
74808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov                MimetypesColumns.MIMETYPE +
74908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        ");");
75008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
751b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Public generic data table
752b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.DATA + " (" +
753b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
75467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                DataColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
755b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                DataColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
75611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                Data.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
75797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                Data.IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
758f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.IS_PRIMARY + " INTEGER NOT NULL DEFAULT 0," +
759f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.IS_SUPER_PRIMARY + " INTEGER NOT NULL DEFAULT 0," +
760f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA_VERSION + " INTEGER NOT NULL DEFAULT 0," +
761f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA1 + " TEXT," +
762f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA2 + " TEXT," +
763f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA3 + " TEXT," +
764f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA4 + " TEXT," +
765f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA5 + " TEXT," +
766f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA6 + " TEXT," +
767f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA7 + " TEXT," +
768f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA8 + " TEXT," +
769f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA9 + " TEXT," +
77067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA10 + " TEXT," +
77167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA11 + " TEXT," +
77267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA12 + " TEXT," +
77367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA13 + " TEXT," +
77467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA14 + " TEXT," +
7753cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.DATA15 + " TEXT," +
7763cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC1 + " TEXT, " +
7773cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC2 + " TEXT, " +
7783cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC3 + " TEXT, " +
7793cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC4 + " TEXT " +
780b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
781b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
78211944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        db.execSQL("CREATE INDEX data_raw_contact_id ON " + Tables.DATA + " (" +
78311944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                Data.RAW_CONTACT_ID +
78411944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        ");");
78511944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
78611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        /**
78711944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov         * For email lookup and similar queries.
78811944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov         */
789f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov        db.execSQL("CREATE INDEX data_mimetype_data1_index ON " + Tables.DATA + " (" +
79011944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "," +
791f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov                Data.DATA1 +
79211944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        ");");
79311944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
794b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Private phone numbers table used for lookup
795b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" +
796f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.DATA_ID
797892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        + " INTEGER REFERENCES data(_id) NOT NULL," +
7985ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID
7995ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
80036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL," +
80136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL" +
802b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
803b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
804b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" +
805f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + "," +
806f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
807b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.DATA_ID +
808b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
809b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
81036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
81136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
81236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
81336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
81436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        ");");
81536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
816a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        // Private name/nickname table used for lookup
817a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.NAME_LOOKUP + " (" +
81814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                NameLookupColumns.DATA_ID
81914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                        + " INTEGER REFERENCES data(_id) NOT NULL," +
8205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID
8215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
82211944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                NameLookupColumns.NORMALIZED_NAME + " TEXT NOT NULL," +
82311944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                NameLookupColumns.NAME_TYPE + " INTEGER NOT NULL," +
82414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                "PRIMARY KEY ("
82514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                        + NameLookupColumns.DATA_ID + ", "
82611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                        + NameLookupColumns.NORMALIZED_NAME + ", "
82711944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                        + NameLookupColumns.NAME_TYPE + ")" +
828a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        ");");
829a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
83014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        db.execSQL("CREATE INDEX name_lookup_raw_contact_id_index ON " + Tables.NAME_LOOKUP + " (" +
83114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID +
83214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        ");");
83314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov
834b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.NICKNAME_LOOKUP + " (" +
835b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + " TEXT," +
836b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.CLUSTER + " TEXT" +
837b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        ");");
838b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
839b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX nickname_lookup_index ON " + Tables.NICKNAME_LOOKUP + " (" +
840b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + ", " +
841b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.CLUSTER +
842b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        ");");
843b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
844ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // Groups table
845ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.GROUPS + " (" +
846ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
84767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                GroupsColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
848035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana                Groups.ACCOUNT_NAME + " STRING DEFAULT NULL, " +
849035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana                Groups.ACCOUNT_TYPE + " STRING DEFAULT NULL, " +
850ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups.SOURCE_ID + " TEXT," +
8519261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                Groups.VERSION + " INTEGER NOT NULL DEFAULT 1," +
85273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov                Groups.DIRTY + " INTEGER NOT NULL DEFAULT 0," +
853ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups.TITLE + " TEXT," +
85467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Groups.TITLE_RES + " INTEGER," +
8550f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov                Groups.NOTES + " TEXT," +
8560f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov                Groups.SYSTEM_ID + " TEXT," +
85794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana                Groups.DELETED + " INTEGER NOT NULL DEFAULT 0," +
858eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Groups.GROUP_VISIBLE + " INTEGER NOT NULL DEFAULT 0," +
859ea547d55f864133861b2db44221ae0c2ac6c1a68Fred Quintana                Groups.SHOULD_SYNC + " INTEGER NOT NULL DEFAULT 1," +
860dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                Groups.AUTO_ADD + " INTEGER NOT NULL DEFAULT 0," +
861dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                Groups.FAVORITES + " INTEGER NOT NULL DEFAULT 0," +
862c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                Groups.GROUP_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
8633cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC1 + " TEXT, " +
8643cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC2 + " TEXT, " +
8653cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC3 + " TEXT, " +
8663cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC4 + " TEXT " +
867ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        ");");
868ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
8695f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        db.execSQL("CREATE INDEX groups_source_id_index ON " + Tables.GROUPS + " (" +
8705f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.SOURCE_ID + ", " +
8715f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.ACCOUNT_TYPE + ", " +
8725f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.ACCOUNT_NAME +
8735f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        ");");
8745f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov
875b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.AGGREGATION_EXCEPTIONS + " (" +
876b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                AggregationExceptionColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
877b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                AggregationExceptions.TYPE + " INTEGER NOT NULL, " +
8780c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1
8795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id), " +
8800c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2
8815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id)" +
882b0160a0bcf6d59eaa43fd501e124b95f873e0157Marc Blank        ");");
883b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
884b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index1 ON " +
885b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                Tables.AGGREGATION_EXCEPTIONS + " (" +
8860c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1 + ", " +
8870c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2 +
888b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        ");");
889b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
890b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index2 ON " +
891b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                Tables.AGGREGATION_EXCEPTIONS + " (" +
8920c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2 + ", " +
8930c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1 +
894b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        ");");
895b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
896eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.SETTINGS + " (" +
897eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.ACCOUNT_NAME + " STRING NOT NULL," +
898eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.ACCOUNT_TYPE + " STRING NOT NULL," +
899eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.UNGROUPED_VISIBLE + " INTEGER NOT NULL DEFAULT 0," +
900eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.SHOULD_SYNC + " INTEGER NOT NULL DEFAULT 1, " +
901eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                "PRIMARY KEY (" + Settings.ACCOUNT_NAME + ", " +
902e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    Settings.ACCOUNT_TYPE + ") ON CONFLICT REPLACE" +
903eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        ");");
904eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey
9054394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.VISIBLE_CONTACTS + " (" +
9064394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
9074394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
9084394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
909385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DEFAULT_DIRECTORY + " (" +
910385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
911385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        ");");
912385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
913e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        // The table for recent calls is here so we can do table joins
914e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        // on people, phones, and calls all in one place.
915e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.CALLS + " (" +
916e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
917e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.NUMBER + " TEXT," +
918e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.DATE + " INTEGER," +
919e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.DURATION + " INTEGER," +
920e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.TYPE + " INTEGER," +
921e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.NEW + " INTEGER," +
922e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NAME + " TEXT," +
923e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NUMBER_TYPE + " INTEGER," +
9242530512f639c4979fd7371c7dd25dd67e8118124Bai Tao                Calls.CACHED_NUMBER_LABEL + " TEXT," +
9252530512f639c4979fd7371c7dd25dd67e8118124Bai Tao                Calls.COUNTRY_ISO + " TEXT" + ");");
926e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov
927b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Activities table
928b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.ACTIVITIES + " (" +
929b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
93067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                ActivitiesColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
931b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                ActivitiesColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
932b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.RAW_ID + " TEXT," +
933499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.IN_REPLY_TO + " TEXT," +
9345ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Activities.AUTHOR_CONTACT_ID +  " INTEGER REFERENCES raw_contacts(_id)," +
9355ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Activities.TARGET_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
936b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.PUBLISHED + " INTEGER NOT NULL," +
937499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.THREAD_PUBLISHED + " INTEGER NOT NULL," +
938b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.TITLE + " TEXT NOT NULL," +
939b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.SUMMARY + " TEXT," +
940adb55c2d8295d300961d86a3605c8ddc469cd4a2Dmitri Plotnikov                Activities.LINK + " TEXT, " +
941b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.THUMBNAIL + " BLOB" +
942b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
943b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
944a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.STATUS_UPDATES + " (" +
945a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                StatusUpdatesColumns.DATA_ID + " INTEGER PRIMARY KEY REFERENCES data(_id)," +
9460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS + " TEXT," +
9470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_TIMESTAMP + " INTEGER," +
9480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_RES_PACKAGE + " TEXT, " +
9490a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_LABEL + " INTEGER, " +
9500a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_ICON + " INTEGER" +
951a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        ");");
952a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov
953b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.PROPERTIES + " (" +
954b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_KEY + " TEXT PRIMARY KEY, " +
955b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_VALUE + " TEXT " +
956b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ");");
957b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
958743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.ACCOUNTS + " (" +
959743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov                RawContacts.ACCOUNT_NAME + " TEXT, " +
960743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + " TEXT " +
961743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        ");");
962743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
963743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // Allow contacts without any account to be created for now.  Achieve that
964743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // by inserting a fake account with both type and name as NULL.
965743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // This "account" should be eliminated as soon as the first real writable account
966743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // is added to the phone.
967743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        db.execSQL("INSERT INTO accounts VALUES(NULL, NULL)");
968743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
969d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        createDirectoriesTable(db);
970d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
971a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        createContactsViews(db);
972a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        createGroupsView(db);
973fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        createContactsTriggers(db);
974916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        createContactsIndexes(db);
9754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
976a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        loadNicknameLookupTable(db);
977a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
978a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        // Add the legacy API support views, etc
979a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        LegacyApiSupport.createDatabase(db);
980a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
981a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        // This will create a sqlite_stat1 table that is used for query optimization
982a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("ANALYZE;");
983a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
984a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        updateSqliteStats(db);
985a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
986a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        // We need to close and reopen the database connection so that the stats are
987a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        // taken into account. Make a note of it and do the actual reopening in the
988a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        // getWritableDatabase method.
989a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        mReopenDatabase = true;
990a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
991a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        ContentResolver.requestSync(null /* all accounts */,
992a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                ContactsContract.AUTHORITY, new Bundle());
993a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    }
994a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
995d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    private void createDirectoriesTable(SQLiteDatabase db) {
996d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DIRECTORIES + "(" +
997d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
998d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.PACKAGE_NAME + " TEXT NOT NULL," +
999d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.DIRECTORY_AUTHORITY + " TEXT NOT NULL," +
1000d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.TYPE_RESOURCE_ID + " INTEGER," +
1001e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov                DirectoryColumns.TYPE_RESOURCE_NAME + " TEXT," +
1002d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.ACCOUNT_TYPE + " TEXT," +
1003d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.ACCOUNT_NAME + " TEXT," +
1004d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.DISPLAY_NAME + " TEXT, " +
1005d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.EXPORT_SUPPORT + " INTEGER NOT NULL" +
100697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                        " DEFAULT " + Directory.EXPORT_SUPPORT_NONE + "," +
100797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                Directory.SHORTCUT_SUPPORT + " INTEGER NOT NULL" +
10083d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        " DEFAULT " + Directory.SHORTCUT_SUPPORT_NONE + "," +
10093d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                Directory.PHOTO_SUPPORT + " INTEGER NOT NULL" +
10103d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        " DEFAULT " + Directory.PHOTO_SUPPORT_NONE +
1011d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        ");");
1012d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
10133d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        // Trigger a full scan of directories in the system
10143d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        setProperty(db, ContactDirectoryManager.PROPERTY_DIRECTORY_SCAN_COMPLETE, "0");
1015d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    }
1016d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
1017916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    private static void createContactsTriggers(SQLiteDatabase db) {
1018fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1019fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        /*
1020fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * Automatically delete Data rows when a raw contact is deleted.
1021fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         */
1022fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.RAW_CONTACTS + "_deleted;");
1023fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_deleted "
1024fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   BEFORE DELETE ON " + Tables.RAW_CONTACTS
1025fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1026fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.DATA
1027fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Data.RAW_CONTACT_ID
1028fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID + ";"
1029fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.AGGREGATION_EXCEPTIONS
1030fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + AggregationExceptions.RAW_CONTACT_ID1
1031fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID
1032fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "        OR " + AggregationExceptions.RAW_CONTACT_ID2
1033fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID + ";"
103435da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "   DELETE FROM " + Tables.VISIBLE_CONTACTS
103535da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
103635da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
103735da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
103835da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "           )=1;"
1039385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "   DELETE FROM " + Tables.DEFAULT_DIRECTORY
1040385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
1041385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
1042385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
1043385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "           )=1;"
1044fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.CONTACTS
1045fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
1046fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
1047fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
1048fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "           )=1;"
1049fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1050fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1051fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1052fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS contacts_times_contacted;");
10536c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        db.execSQL("DROP TRIGGER IF EXISTS raw_contacts_times_contacted;");
1054fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1055fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        /*
1056fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * Triggers that update {@link RawContacts#VERSION} when the contact is
1057fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * marked for deletion or any time a data row is inserted, updated or
1058fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * deleted.
1059fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         */
1060fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.RAW_CONTACTS + "_marked_deleted;");
1061fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_marked_deleted "
10627f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori                + "   AFTER UPDATE ON " + Tables.RAW_CONTACTS
1063fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1064fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1065fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET "
1066fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                +         RawContacts.VERSION + "=OLD." + RawContacts.VERSION + "+1 "
1067fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + RawContacts._ID
1068fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "       AND NEW." + RawContacts.DELETED + "!= OLD." + RawContacts.DELETED + ";"
1069fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1070fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1071fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.DATA + "_updated;");
10727f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_updated AFTER UPDATE ON " + Tables.DATA
1073fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1074fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.DATA
1075fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + Data.DATA_VERSION + "=OLD." + Data.DATA_VERSION + "+1 "
1076fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Data._ID + "=OLD." + Data._ID + ";"
1077fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1078fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + RawContacts.VERSION + "=" + RawContacts.VERSION + "+1 "
1079fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + Data.RAW_CONTACT_ID + ";"
1080fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1081fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1082fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.DATA + "_deleted;");
1083fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_deleted BEFORE DELETE ON " + Tables.DATA
1084fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1085fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1086fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + RawContacts.VERSION + "=" + RawContacts.VERSION + "+1 "
1087fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + Data.RAW_CONTACT_ID + ";"
1088fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.PHONE_LOOKUP
1089fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + PhoneLookupColumns.DATA_ID + "=OLD." + Data._ID + ";"
1090fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.STATUS_UPDATES
1091fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + StatusUpdatesColumns.DATA_ID + "=OLD." + Data._ID + ";"
1092fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.NAME_LOOKUP
1093fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + NameLookupColumns.DATA_ID + "=OLD." + Data._ID + ";"
1094fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1095fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1096fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1097fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.GROUPS + "_updated1;");
1098fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.GROUPS + "_updated1 "
10997f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori                + "   AFTER UPDATE ON " + Tables.GROUPS
1100fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1101fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.GROUPS
1102fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET "
1103fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                +         Groups.VERSION + "=OLD." + Groups.VERSION + "+1"
1104fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Groups._ID + "=OLD." + Groups._ID + ";"
1105fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1106fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov    }
1107fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1108916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    private static void createContactsIndexes(SQLiteDatabase db) {
1109916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
1110916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        db.execSQL("CREATE INDEX name_lookup_index ON " + Tables.NAME_LOOKUP + " (" +
1111916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.NORMALIZED_NAME + "," +
1112916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.NAME_TYPE + ", " +
1113916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID + ", " +
1114916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.DATA_ID +
1115916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        ");");
111604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
111704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS raw_contact_sort_key1_index");
111804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
111904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                RawContacts.SORT_KEY_PRIMARY +
112004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        ");");
112104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
112204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS raw_contact_sort_key2_index");
112304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key2_index ON " + Tables.RAW_CONTACTS + " (" +
112404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                RawContacts.SORT_KEY_ALTERNATIVE +
112504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        ");");
1126916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    }
1127916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov
1128a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    private static void createContactsViews(SQLiteDatabase db) {
1129a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.CONTACTS_ALL + ";");
1130a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.CONTACTS_RESTRICTED + ";");
1131a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.DATA_ALL + ";");
1132a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.DATA_RESTRICTED + ";");
1133a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_CONTACTS_ALL + ";");
1134a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_CONTACTS_RESTRICTED + ";");
1135a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_ENTITIES + ";");
1136a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_ENTITIES_RESTRICTED + ";");
1137a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.ENTITIES + ";");
1138a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.ENTITIES_RESTRICTED + ";");
1139a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
11404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String dataColumns =
11414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                Data.IS_PRIMARY + ", "
11424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.IS_SUPER_PRIMARY + ", "
11434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA_VERSION + ", "
11444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + PackagesColumns.PACKAGE + " AS " + Data.RES_PACKAGE + ","
11454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + MimetypesColumns.MIMETYPE + " AS " + Data.MIMETYPE + ", "
114697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + Data.IS_READ_ONLY + ", "
11474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA1 + ", "
11484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA2 + ", "
11494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA3 + ", "
11504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA4 + ", "
11514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA5 + ", "
11524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA6 + ", "
11534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA7 + ", "
11544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA8 + ", "
11554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA9 + ", "
11564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA10 + ", "
11574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA11 + ", "
11584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA12 + ", "
11594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA13 + ", "
11604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA14 + ", "
11614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA15 + ", "
11624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC1 + ", "
11634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC2 + ", "
11644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC3 + ", "
11654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC4;
11664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
11674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String syncColumns =
11684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AS " + RawContacts.ACCOUNT_NAME + ","
11694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AS " + RawContacts.ACCOUNT_TYPE + ","
11704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SOURCE_ID + " AS " + RawContacts.SOURCE_ID + ","
1171f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                + RawContactsColumns.CONCRETE_NAME_VERIFIED + " AS " + RawContacts.NAME_VERIFIED + ","
11724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_VERSION + " AS " + RawContacts.VERSION + ","
11734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DIRTY + " AS " + RawContacts.DIRTY + ","
11744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC1 + " AS " + RawContacts.SYNC1 + ","
11754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC2 + " AS " + RawContacts.SYNC2 + ","
11764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC3 + " AS " + RawContacts.SYNC3 + ","
11774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC4 + " AS " + RawContacts.SYNC4;
11784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
11793d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        String baseContactColumns =
11803d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                Contacts.HAS_PHONE_NUMBER + ", "
11813d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.NAME_RAW_CONTACT_ID + ", "
11823d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.LOOKUP_KEY + ", "
11833d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.PHOTO_ID + ", "
11843d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Clauses.CONTACT_VISIBLE + " AS " + Contacts.IN_VISIBLE_GROUP + ", "
11853d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + ContactsColumns.LAST_STATUS_UPDATE_ID;
11863d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
11874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactOptionColumns =
11884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.CONCRETE_CUSTOM_RINGTONE
11894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.CUSTOM_RINGTONE + ","
11904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL
11914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.SEND_TO_VOICEMAIL + ","
11924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_LAST_TIME_CONTACTED
11934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.LAST_TIME_CONTACTED + ","
11944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_TIMES_CONTACTED
11954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.TIMES_CONTACTED + ","
11964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_STARRED
11974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.STARRED;
11984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
11995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String contactNameColumns =
12005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "name_raw_contact." + RawContacts.DISPLAY_NAME_SOURCE
12015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_SOURCE + ", "
12025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.DISPLAY_NAME_PRIMARY
12035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_PRIMARY + ", "
12045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.DISPLAY_NAME_ALTERNATIVE
12055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_ALTERNATIVE + ", "
12065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.PHONETIC_NAME
12075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.PHONETIC_NAME + ", "
12085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.PHONETIC_NAME_STYLE
12095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.PHONETIC_NAME_STYLE + ", "
12105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.SORT_KEY_PRIMARY
12115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.SORT_KEY_PRIMARY + ", "
12125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.SORT_KEY_ALTERNATIVE
12134394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        + " AS " + Contacts.SORT_KEY_ALTERNATIVE;
12145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
12154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String dataSelect = "SELECT "
12164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + Data._ID + ","
12174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.RAW_CONTACT_ID + ", "
1218fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + RawContacts.CONTACT_ID + ", "
12194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + syncColumns + ", "
12204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + dataColumns + ", "
12214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + contactOptionColumns + ", "
12225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + contactNameColumns + ", "
12233d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + baseContactColumns + ", "
12243d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
12253d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_URI) + ", "
12263d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
12273d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_THUMBNAIL_URI) + ", "
12284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
12294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.DATA
1230a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.MIMETYPES + " ON ("
12314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1232a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " ON ("
12334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1234a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.CONTACTS + " ON ("
1235fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   RawContactsColumns.CONCRETE_CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID + ")"
1236fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1237fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")"
1238a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1239a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
12404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
12414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1242f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1243a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                        + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
12444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.DATA_ALL + " AS " + dataSelect);
12464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.DATA_RESTRICTED + " AS " + dataSelect + " WHERE "
1247fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0");
12484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String rawContactOptionColumns =
12504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                RawContacts.CUSTOM_RINGTONE + ","
12514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.SEND_TO_VOICEMAIL + ","
12524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.LAST_TIME_CONTACTED + ","
12534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.TIMES_CONTACTED + ","
12544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.STARRED;
12554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String rawContactsSelect = "SELECT "
12574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + RawContacts._ID + ","
12584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.CONTACT_ID + ", "
12594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.AGGREGATION_MODE + ", "
126097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + RawContacts.RAW_CONTACT_IS_READ_ONLY + ", "
12614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.DELETED + ", "
12625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_SOURCE  + ", "
12635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_PRIMARY  + ", "
12645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_ALTERNATIVE  + ", "
12655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.PHONETIC_NAME  + ", "
12665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.PHONETIC_NAME_STYLE  + ", "
12675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.SORT_KEY_PRIMARY  + ", "
12685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.SORT_KEY_ALTERNATIVE + ", "
12694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + rawContactOptionColumns + ", "
12704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + syncColumns
12714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS;
12724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_CONTACTS_ALL + " AS " + rawContactsSelect);
12744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_CONTACTS_RESTRICTED + " AS " + rawContactsSelect
12754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " WHERE " + RawContacts.IS_RESTRICTED + "=0");
12764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactsColumns =
12784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.CONCRETE_CUSTOM_RINGTONE
12794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.CUSTOM_RINGTONE + ", "
12805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + contactNameColumns + ", "
12813d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + baseContactColumns + ", "
12824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_LAST_TIME_CONTACTED
12834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.LAST_TIME_CONTACTED + ", "
12844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL
12854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.SEND_TO_VOICEMAIL + ", "
12864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_STARRED
12874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.STARRED + ", "
12884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_TIMES_CONTACTED
12893d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        + " AS " + Contacts.TIMES_CONTACTED;
12904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactsSelect = "SELECT "
12924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_ID + " AS " + Contacts._ID + ","
12933d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + contactsColumns + ", "
12943d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(ContactsColumns.CONCRETE_ID, Contacts.PHOTO_URI) + ", "
12953d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(ContactsColumns.CONCRETE_ID, Contacts.PHOTO_THUMBNAIL_URI)
12964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.CONTACTS
1297fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1298fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")";
12994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.CONTACTS_ALL + " AS " + contactsSelect);
1301fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.CONTACTS_RESTRICTED + " AS " + contactsSelect
1302fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " WHERE " + ContactsColumns.SINGLE_IS_RESTRICTED + "=0");
1303a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1304a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        String rawEntitiesSelect = "SELECT "
1305a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContacts.CONTACT_ID + ", "
1306a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DELETED + " AS " + RawContacts.DELETED + ","
1307a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + dataColumns + ", "
1308a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + syncColumns + ", "
1309a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC1 + ", "
1310a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC2 + ", "
1311a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC3 + ", "
1312a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC4 + ", "
1313a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + RawContacts._ID + ", "
1314a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + RawContacts.Entity.DATA_ID + ","
1315a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_STARRED + " AS " + RawContacts.STARRED + ","
1316a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED + " AS "
1317a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                        + RawContacts.IS_RESTRICTED + ","
1318a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
1319a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS
1320a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.DATA + " ON ("
1321a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1322a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1323a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
1324a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.MIMETYPES + " ON ("
1325a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1326a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
1327a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1328a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1329a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
1330a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1331a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_ENTITIES + " AS "
1332a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + rawEntitiesSelect);
1333a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_ENTITIES_RESTRICTED + " AS "
1334a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + rawEntitiesSelect + " WHERE " + RawContacts.IS_RESTRICTED + "=0");
1335a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1336a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        String entitiesSelect = "SELECT "
1337a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + Contacts._ID + ", "
1338a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + RawContacts.CONTACT_ID + ", "
1339a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DELETED + " AS " + RawContacts.DELETED + ","
1340a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED
1341a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                        + " AS " + RawContacts.IS_RESTRICTED + ","
1342a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + dataColumns + ", "
1343a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + syncColumns + ", "
1344a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + contactsColumns + ", "
13453d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
13463d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_URI) + ", "
13473d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
13483d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_THUMBNAIL_URI) + ", "
1349a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC1 + ", "
1350a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC2 + ", "
1351a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC3 + ", "
1352a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC4 + ", "
1353a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + Contacts.Entity.RAW_CONTACT_ID + ", "
1354a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + Contacts.Entity.DATA_ID + ","
1355a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
1356a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS
1357a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " JOIN " + Tables.CONTACTS + " ON ("
1358a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   RawContactsColumns.CONCRETE_CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID + ")"
1359a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1360a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")"
1361a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.DATA + " ON ("
1362a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1363a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1364a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
1365a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.MIMETYPES + " ON ("
1366a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1367a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
1368a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1369a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1370a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
1371a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1372a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.ENTITIES + " AS "
1373a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + entitiesSelect);
1374a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.ENTITIES_RESTRICTED + " AS "
1375a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + entitiesSelect + " WHERE " + RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0");
1376a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    }
13774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13783d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    private static String buildPhotoUriAlias(String contactIdColumn, String alias) {
13792b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        return "(CASE WHEN " + Contacts.PHOTO_ID + " IS NULL"
13802b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " OR " + Contacts.PHOTO_ID + "=0"
13812b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " THEN NULL"
13822b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " ELSE " + "'" + Contacts.CONTENT_URI + "/'||"
13832b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                        + contactIdColumn + "|| '/" + Photo.CONTENT_DIRECTORY + "'"
13842b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " END)"
13852b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " AS " + alias;
13863d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
13873d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
1388a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    private static void createGroupsView(SQLiteDatabase db) {
1389a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.GROUPS_ALL + ";");
139089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        String groupsColumns =
139189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                Groups.ACCOUNT_NAME + ","
139289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.ACCOUNT_TYPE + ","
139389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SOURCE_ID + ","
139489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.VERSION + ","
139589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.DIRTY + ","
139689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.TITLE + ","
139789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.TITLE_RES + ","
139889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.NOTES + ","
139989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYSTEM_ID + ","
140089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.DELETED + ","
140189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.GROUP_VISIBLE + ","
140289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SHOULD_SYNC + ","
1403dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + Groups.AUTO_ADD + ","
1404dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + Groups.FAVORITES + ","
1405c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                + Groups.GROUP_IS_READ_ONLY + ","
140689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC1 + ","
140789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC2 + ","
140889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC3 + ","
140989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC4 + ","
141089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + PackagesColumns.PACKAGE + " AS " + Groups.RES_PACKAGE;
141189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
141289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        String groupsSelect = "SELECT "
141389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + GroupsColumns.CONCRETE_ID + " AS " + Groups._ID + ","
141489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + groupsColumns
141589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + " FROM " + Tables.GROUPS_JOIN_PACKAGES;
141689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
141789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.GROUPS_ALL + " AS " + groupsSelect);
1418b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
1419b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1420b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
1421b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
142246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion < 99) {
142346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion
142446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana                    + ", data will be lost!");
142546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
142646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.CONTACTS + ";");
142746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.RAW_CONTACTS + ";");
142846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.PACKAGES + ";");
142946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.MIMETYPES + ";");
143046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.DATA + ";");
143146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.PHONE_LOOKUP + ";");
143246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.NAME_LOOKUP + ";");
143346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.NICKNAME_LOOKUP + ";");
143446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.GROUPS + ";");
143546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.ACTIVITIES + ";");
143646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.CALLS + ";");
143746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.SETTINGS + ";");
143846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.STATUS_UPDATES + ";");
143946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
144046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // TODO: we should not be dropping agg_exceptions and contact_options. In case that
144146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // table's schema changes, we should try to preserve the data, because it was entered
144246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // by the user and has never been synched to the server.
144346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.AGGREGATION_EXCEPTIONS + ";");
144446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
144546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            onCreate(db);
144646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            return;
144746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
1448f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
144946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion);
1450a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
145108e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        boolean upgradeViewsAndTriggers = false;
145204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        boolean upgradeNameLookup = false;
145308e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov
145446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion == 99) {
145508e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
145646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            oldVersion++;
145746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
145846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
1459a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        if (oldVersion == 100) {
1460a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            db.execSQL("CREATE INDEX IF NOT EXISTS mimetypes_mimetype_index ON "
1461a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                    + Tables.MIMETYPES + " ("
1462a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                            + MimetypesColumns.MIMETYPE + ","
1463a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                            + MimetypesColumns._ID + ");");
1464a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            updateIndexStats(db, Tables.MIMETYPES,
1465a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                    "mimetypes_mimetype_index", "50 1 1");
1466a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
146708e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1468a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            oldVersion++;
1469a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        }
1470a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1471fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        if (oldVersion == 101) {
147208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1473fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov            oldVersion++;
1474fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        }
1475fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
147647ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov        if (oldVersion == 102) {
147708e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
147847ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov            oldVersion++;
147947ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov        }
148047ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov
148136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        if (oldVersion == 103) {
148208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1483bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey            oldVersion++;
1484bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey        }
1485bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey
148671037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov        if (oldVersion == 104 || oldVersion == 201) {
148771037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov            LegacyApiSupport.createSettingsTable(db);
148808e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
14893410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov            oldVersion++;
14903410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov        }
14913410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov
149271037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov        if (oldVersion == 105) {
14935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion202(db);
149404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            upgradeNameLookup = true;
14953410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov            oldVersion = 202;
149636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        }
149736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
1498fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        if (oldVersion == 202) {
14995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion203(db);
150008e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1501fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov            oldVersion++;
1502fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        }
1503fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
15049b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori        if (oldVersion == 203) {
150508e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
15069b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori            oldVersion++;
15079b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori        }
15089b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori
15095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (oldVersion == 204) {
15105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion205(db);
151108e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
15125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            oldVersion++;
15135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
15145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
1515f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        if (oldVersion == 205) {
1516f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            upgrateToVersion206(db);
1517f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1518f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            oldVersion++;
1519f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        }
1520f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov
152131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        if (oldVersion == 206) {
1522b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeToVersion300(db);
152334469970fb04b9b188b5430f592b0c956a6ea2aaDmitri Plotnikov            oldVersion = 300;
152431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
152531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
15266c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        if (oldVersion == 300) {
15276c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook            upgradeViewsAndTriggers = true;
15286c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook            oldVersion = 301;
15296c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        }
15306c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook
1531916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        if (oldVersion == 301) {
1532916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1533916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            oldVersion = 302;
1534916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        }
1535916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov
1536b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (oldVersion == 302) {
1537b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeEmailToVersion303(db);
1538b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeNicknameToVersion303(db);
1539b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            oldVersion = 303;
1540b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
1541b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
154208768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        if (oldVersion == 303) {
154308768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            upgradeToVersion304(db);
154408768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            oldVersion = 304;
154508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        }
154608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
1547f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        if (oldVersion == 304) {
1548f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee            upgradeNameLookup = true;
1549f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee            oldVersion = 305;
1550f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        }
1551f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee
155260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        if (oldVersion == 305) {
155360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            upgradeToVersion306(db);
155460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            oldVersion = 306;
155560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        }
155660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
1557b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        if (oldVersion == 306) {
1558b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            upgradeToVersion307(db);
1559b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            oldVersion = 307;
1560b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        }
1561b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
1562743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        if (oldVersion == 307) {
1563743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov            upgradeToVersion308(db);
1564743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov            oldVersion = 308;
1565743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        }
1566743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
156794c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        // Gingerbread upgrades
156894c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        if (oldVersion < 350) {
1569afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann            upgradeViewsAndTriggers = true;
157094c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            oldVersion = 351;
1571afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann        }
1572afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann
157394c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        if (oldVersion == 351) {
157494c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            upgradeNameLookup = true;
157594c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            oldVersion = 352;
157680d7871ca31d604cbfd857661d5300bb090076dbDaniel Lehmann        }
157780d7871ca31d604cbfd857661d5300bb090076dbDaniel Lehmann
15787da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        if (oldVersion == 352) {
15797da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            upgradeToVersion353(db);
15807da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            oldVersion = 353;
15817da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        }
15827da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
1583f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        // Honeycomb upgrades
1584f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        if (oldVersion < 400) {
1585dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana            upgradeViewsAndTriggers = true;
1586f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov            upgradeToVersion400(db);
1587f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov            oldVersion = 400;
1588dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        }
1589dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana
1590f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        if (oldVersion == 400) {
15914394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            upgradeViewsAndTriggers = true;
15924394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            upgradeToVersion401(db);
15934394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            oldVersion = 401;
15944394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        }
15954394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
1596d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        if (oldVersion == 401) {
1597d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov            upgradeToVersion402(db);
1598d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov            oldVersion = 402;
1599d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        }
1600d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
160197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        if (oldVersion == 402) {
160297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            upgradeViewsAndTriggers = true;
160397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            upgradeToVersion403(db);
160497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            oldVersion = 403;
160597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        }
160697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
1607a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        if (oldVersion == 403) {
1608a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1609a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov            oldVersion = 404;
1610a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        }
1611a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1612892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (oldVersion == 404) {
1613892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1614892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            upgradeToVersion405(db);
1615892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            oldVersion = 405;
1616892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
1617892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
16182530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        if (oldVersion == 405) {
16192530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            upgradeViewsAndTriggers = true;
16202530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            upgradeToVersion406(db);
16212530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            oldVersion = 406;
16222530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        }
16232530512f639c4979fd7371c7dd25dd67e8118124Bai Tao
1624cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov        if (oldVersion == 406) {
1625cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1626cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov            oldVersion = 407;
1627cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov        }
1628cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov
1629385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        if (oldVersion == 407) {
1630d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            // Obsolete
1631385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            oldVersion = 408;
1632385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        }
1633385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
16343d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        if (oldVersion == 408) {
16353d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            upgradeViewsAndTriggers = true;
16363d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            upgradeToVersion409(db);
16373d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            oldVersion = 409;
16383d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        }
16393d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
16402b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        if (oldVersion == 409) {
16412b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov            upgradeViewsAndTriggers = true;
16422b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov            oldVersion = 410;
16432b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        }
16442b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov
1645d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        if (oldVersion == 410) {
1646d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            upgradeToVersion411(db);
1647d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            oldVersion = 411;
1648d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        }
1649d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov
16507da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        if (oldVersion == 411) {
16517da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            // Same upgrade as 353, only on Honeycomb devices
16527da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            upgradeToVersion353(db);
16537da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            oldVersion = 412;
16547da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        }
16557da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
1656e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov        if (oldVersion == 412) {
1657e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov            upgradeToVersion413(db);
1658e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov            oldVersion = 413;
1659e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov        }
1660e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov
166156f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee        if (oldVersion == 413) {
166256f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee            upgradeNameLookup = true;
166356f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee            oldVersion = 414;
166456f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee        }
166556f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee
1666c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        if (oldVersion == 414) {
1667c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            upgradeToVersion415(db);
1668c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1669c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            oldVersion = 415;
1670c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        }
1671c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov
167208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        if (upgradeViewsAndTriggers) {
167308e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createContactsViews(db);
167408e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createGroupsView(db);
167508e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createContactsTriggers(db);
1676916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            createContactsIndexes(db);
167708e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            LegacyApiSupport.createViews(db);
1678916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            updateSqliteStats(db);
1679916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            mReopenDatabase = true;
168008e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        }
168108e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov
168204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (upgradeNameLookup) {
168304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            rebuildNameLookup(db);
168404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
168504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
168646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion != newVersion) {
168746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            throw new IllegalStateException(
168846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana                    "error upgrading the database to version " + newVersion);
168946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
1690b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
1691b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
16925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion202(SQLiteDatabase db) {
169336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL(
169436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "ALTER TABLE " + Tables.PHONE_LOOKUP +
169536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " ADD " + PhoneLookupColumns.MIN_MATCH + " TEXT;");
169636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
169736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
169836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
169936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
170036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
170136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        ");");
170236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
170336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        updateIndexStats(db, Tables.PHONE_LOOKUP,
170436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "phone_lookup_min_match_index", "10000 2 2 1");
170536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
170636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        SQLiteStatement update = db.compileStatement(
170736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "UPDATE " + Tables.PHONE_LOOKUP +
170836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " SET " + PhoneLookupColumns.MIN_MATCH + "=?" +
170936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " WHERE " + PhoneLookupColumns.DATA_ID + "=?");
171036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
171136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        // Populate the new column
171236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        Cursor c = db.query(Tables.PHONE_LOOKUP + " JOIN " + Tables.DATA +
171336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " ON (" + PhoneLookupColumns.DATA_ID + "=" + DataColumns.CONCRETE_ID + ")",
171436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                new String[]{Data._ID, Phone.NUMBER}, null, null, null, null, null);
171536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        try {
171636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            while (c.moveToNext()) {
171736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                long dataId = c.getLong(0);
171836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                String number = c.getString(1);
171936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                if (!TextUtils.isEmpty(number)) {
172036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.bindString(1, PhoneNumberUtils.toCallerIDMinMatch(number));
172136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.bindLong(2, dataId);
172236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.execute();
172336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                }
172436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            }
172536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        } finally {
172636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            c.close();
172736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        }
172836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    }
172936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
17305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion203(SQLiteDatabase db) {
1731758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // Garbage-collect first. A bug in Eclair was sometimes leaving
1732758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // raw_contacts in the database that no longer had contacts associated
1733758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // with them.  To avoid failures during this database upgrade, drop
1734758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // the orphaned raw_contacts.
1735758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        db.execSQL(
1736758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                "DELETE FROM raw_contacts" +
1737758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                " WHERE contact_id NOT NULL" +
1738758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                " AND contact_id NOT IN (SELECT _id FROM contacts)");
1739758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov
1740fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1741fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "ALTER TABLE " + Tables.CONTACTS +
1742fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " ADD " + Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)");
1743fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1744fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "ALTER TABLE " + Tables.RAW_CONTACTS +
17454394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " ADD contact_in_visible_group INTEGER NOT NULL DEFAULT 0");
1746fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1747fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // For each Contact, find the RawContact that contributed the display name
1748fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1749fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1750fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.NAME_RAW_CONTACT_ID + "=(" +
1751fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " SELECT " + RawContacts._ID +
1752fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.RAW_CONTACTS +
1753fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
1754fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " AND " + RawContactsColumns.CONCRETE_DISPLAY_NAME + "=" +
1755fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                                Tables.CONTACTS + "." + Contacts.DISPLAY_NAME +
1756fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " ORDER BY " + RawContacts._ID +
1757fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " LIMIT 1)"
1758fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1759fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1760fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_name_raw_contact_id_index ON " + Tables.CONTACTS + " (" +
1761fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID +
1762fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1763fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1764fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // If for some unknown reason we missed some names, let's make sure there are
1765fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // no contacts without a name, picking a raw contact "at random".
1766fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1767fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1768fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.NAME_RAW_CONTACT_ID + "=(" +
1769fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " SELECT " + RawContacts._ID +
1770fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.RAW_CONTACTS +
1771fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
1772fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " ORDER BY " + RawContacts._ID +
1773fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " LIMIT 1)" +
1774fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " WHERE " + Contacts.NAME_RAW_CONTACT_ID + " IS NULL"
1775fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1776fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1777fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // Wipe out DISPLAY_NAME on the Contacts table as it is no longer in use.
1778fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1779fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1780fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.DISPLAY_NAME + "=NULL"
1781fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1782fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1783fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // Copy the IN_VISIBLE_GROUP flag down to all raw contacts to allow
1784fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // indexing on (display_name, in_visible_group)
1785fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1786fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.RAW_CONTACTS +
17874394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " SET contact_in_visible_group=(" +
1788fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        "SELECT " + Contacts.IN_VISIBLE_GROUP +
1789fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.CONTACTS +
1790bcbd6a5cdd2d1aa6531c592428dc20e0282486c3Dmitri Plotnikov                        " WHERE " + Contacts._ID + "=" + RawContacts.CONTACT_ID + ")" +
1791bcbd6a5cdd2d1aa6531c592428dc20e0282486c3Dmitri Plotnikov                " WHERE " + RawContacts.CONTACT_ID + " NOT NULL"
1792fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1793fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1794fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
17954394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
1796fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                RawContactsColumns.DISPLAY_NAME + " COLLATE LOCALIZED ASC" +
1797fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1798fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1799fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("DROP INDEX contacts_visible_index");
1800fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_visible_index ON " + Tables.CONTACTS + " (" +
1801fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.IN_VISIBLE_GROUP +
1802fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1803fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov    }
1804fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
18055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion205(SQLiteDatabase db) {
18065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
18075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.DISPLAY_NAME_ALTERNATIVE + " TEXT;");
18085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
18095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.PHONETIC_NAME + " TEXT;");
18105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
18115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.PHONETIC_NAME_STYLE + " INTEGER;");
18125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
1813de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " ADD " + RawContacts.SORT_KEY_PRIMARY
1814de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " TEXT COLLATE " + ContactsProvider2.PHONEBOOK_COLLATOR_NAME + ";");
18155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
1816de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " ADD " + RawContacts.SORT_KEY_ALTERNATIVE
1817de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " TEXT COLLATE " + ContactsProvider2.PHONEBOOK_COLLATOR_NAME + ";");
18185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        final Locale locale = Locale.getDefault();
18205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
182151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        NameSplitter splitter = createNameSplitter();
18225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement rawContactUpdate = db.compileStatement(
18245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.RAW_CONTACTS +
18255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
18265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.DISPLAY_NAME_PRIMARY + "=?," +
18275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," +
18285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.PHONETIC_NAME + "=?," +
18295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.PHONETIC_NAME_STYLE + "=?," +
18305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.SORT_KEY_PRIMARY + "=?," +
18315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.SORT_KEY_ALTERNATIVE + "=?" +
18325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + RawContacts._ID + "=?");
18335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        upgradeStructuredNamesToVersion205(db, rawContactUpdate, splitter);
18355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        upgradeOrganizationsToVersion205(db, rawContactUpdate, splitter);
18365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("DROP INDEX raw_contact_sort_key1_index");
18385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
18394394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
18405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.SORT_KEY_PRIMARY +
18415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        ");");
18425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key2_index ON " + Tables.RAW_CONTACTS + " (" +
18444394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
18455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.SORT_KEY_ALTERNATIVE +
18465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        ");");
18475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
18485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private interface StructName205Query {
18505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String TABLE = Tables.DATA_JOIN_RAW_CONTACTS;
18515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String COLUMNS[] = {
18535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.CONCRETE_ID,
18545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Data.RAW_CONTACT_ID,
18555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_SOURCE,
18565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_PRIMARY,
18575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PREFIX,
18585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.GIVEN_NAME,
18595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.MIDDLE_NAME,
18605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.FAMILY_NAME,
18615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.SUFFIX,
18625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_FAMILY_NAME,
18635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_MIDDLE_NAME,
18645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_GIVEN_NAME,
18655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        };
18665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int ID = 0;
18685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int RAW_CONTACT_ID = 1;
18695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int DISPLAY_NAME_SOURCE = 2;
18705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int DISPLAY_NAME = 3;
18715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PREFIX = 4;
18725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int GIVEN_NAME = 5;
18735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int MIDDLE_NAME = 6;
18745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int FAMILY_NAME = 7;
18755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int SUFFIX = 8;
18765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_FAMILY_NAME = 9;
18775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_MIDDLE_NAME = 10;
18785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_GIVEN_NAME = 11;
18795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
18805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeStructuredNamesToVersion205(SQLiteDatabase db,
18825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement rawContactUpdate, NameSplitter splitter) {
18835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        // Process structured names to detect the style of the full name and phonetic name
18855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        long mMimeType;
18875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
18885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            mMimeType = DatabaseUtils.longForQuery(db,
18895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    "SELECT " + MimetypesColumns._ID +
18905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    " FROM " + Tables.MIMETYPES +
18915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    " WHERE " + MimetypesColumns.MIMETYPE
18925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                            + "='" + StructuredName.CONTENT_ITEM_TYPE + "'", null);
18935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } catch (SQLiteDoneException e) {
18945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            // No structured names in the database
18955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            return;
18965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
18975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement structuredNameUpdate = db.compileStatement(
18995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.DATA +
19005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
19015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.FULL_NAME_STYLE + "=?," +
19025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.DISPLAY_NAME + "=?," +
19035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.PHONETIC_NAME_STYLE + "=?" +
19045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + Data._ID + "=?");
19055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        NameSplitter.Name name = new NameSplitter.Name();
19075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        StringBuilder sb = new StringBuilder();
19085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        Cursor cursor = db.query(StructName205Query.TABLE,
19095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructName205Query.COLUMNS,
19105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=" + mMimeType, null, null, null, null);
19115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
19125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            while (cursor.moveToNext()) {
19135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long dataId = cursor.getLong(StructName205Query.ID);
19145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long rawContactId = cursor.getLong(StructName205Query.RAW_CONTACT_ID);
19155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                int displayNameSource = cursor.getInt(StructName205Query.DISPLAY_NAME_SOURCE);
19165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String displayName = cursor.getString(StructName205Query.DISPLAY_NAME);
19175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.clear();
19195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.prefix = cursor.getString(StructName205Query.PREFIX);
19205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.givenNames = cursor.getString(StructName205Query.GIVEN_NAME);
19215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.middleName = cursor.getString(StructName205Query.MIDDLE_NAME);
19225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.familyName = cursor.getString(StructName205Query.FAMILY_NAME);
19235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.suffix = cursor.getString(StructName205Query.SUFFIX);
19245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticFamilyName = cursor.getString(StructName205Query.PHONETIC_FAMILY_NAME);
19255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticMiddleName = cursor.getString(StructName205Query.PHONETIC_MIDDLE_NAME);
19265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticGivenName = cursor.getString(StructName205Query.PHONETIC_GIVEN_NAME);
19275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                upgradeNameToVersion205(dataId, rawContactId, displayNameSource, displayName, name,
19295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        structuredNameUpdate, rawContactUpdate, splitter, sb);
19305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
19315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } finally {
19325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            cursor.close();
19335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
19345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
19355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeNameToVersion205(long dataId, long rawContactId, int displayNameSource,
19375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String currentDisplayName, NameSplitter.Name name,
19385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement structuredNameUpdate, SQLiteStatement rawContactUpdate,
19395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            NameSplitter splitter, StringBuilder sb) {
19405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        splitter.guessNameStyle(name);
1942ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        int unadjustedFullNameStyle = name.fullNameStyle;
19435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        name.fullNameStyle = splitter.getAdjustedFullNameStyle(name.fullNameStyle);
19445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String displayName = splitter.join(name, true);
19455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
1946ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        // Don't update database with the adjusted fullNameStyle as it is locale
1947ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        // related
1948ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        structuredNameUpdate.bindLong(1, unadjustedFullNameStyle);
19495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        DatabaseUtils.bindObjectToProgram(structuredNameUpdate, 2, displayName);
19505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.bindLong(3, name.phoneticNameStyle);
19515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.bindLong(4, dataId);
19525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.execute();
19535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (displayNameSource == DisplayNameSources.STRUCTURED_NAME) {
19555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String displayNameAlternative = splitter.join(name, false);
19565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String phoneticName = splitter.joinPhoneticName(name);
19575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String sortKey = null;
19585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String sortKeyAlternative = null;
19595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            if (phoneticName != null) {
19615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKey = sortKeyAlternative = phoneticName;
1962ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao            } else if (name.fullNameStyle == FullNameStyle.CHINESE ||
1963ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                    name.fullNameStyle == FullNameStyle.CJK) {
1964ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                sortKey = sortKeyAlternative = ContactLocaleUtils.getIntance()
1965ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                        .getSortKey(displayName, name.fullNameStyle);
19665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
19675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            if (sortKey == null) {
19695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKey = displayName;
19705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKeyAlternative = displayNameAlternative;
19715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
19725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            updateRawContact205(rawContactUpdate, rawContactId, displayName,
19745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    displayNameAlternative, name.phoneticNameStyle, phoneticName, sortKey,
19755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    sortKeyAlternative);
19765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
19775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
19785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private interface Organization205Query {
19805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String TABLE = Tables.DATA_JOIN_RAW_CONTACTS;
19815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String COLUMNS[] = {
19835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.CONCRETE_ID,
19845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Data.RAW_CONTACT_ID,
19855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Organization.COMPANY,
19865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Organization.PHONETIC_NAME,
19875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        };
19885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int ID = 0;
19905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int RAW_CONTACT_ID = 1;
19915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int COMPANY = 2;
19925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_NAME = 3;
19935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
19945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeOrganizationsToVersion205(SQLiteDatabase db,
19965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement rawContactUpdate, NameSplitter splitter) {
1997b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeType = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
19985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement organizationUpdate = db.compileStatement(
20005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.DATA +
20015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
20025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        Organization.PHONETIC_NAME_STYLE + "=?" +
20035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + Data._ID + "=?");
20045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        Cursor cursor = db.query(Organization205Query.TABLE, Organization205Query.COLUMNS,
2006b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=" + mimeType + " AND "
20075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + RawContacts.DISPLAY_NAME_SOURCE + "=" + DisplayNameSources.ORGANIZATION,
20085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                null, null, null, null);
20095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
20105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            while (cursor.moveToNext()) {
20115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long dataId = cursor.getLong(Organization205Query.ID);
20125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long rawContactId = cursor.getLong(Organization205Query.RAW_CONTACT_ID);
20135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String company = cursor.getString(Organization205Query.COMPANY);
20145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String phoneticName = cursor.getString(Organization205Query.PHONETIC_NAME);
20155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                int phoneticNameStyle = splitter.guessPhoneticNameStyle(phoneticName);
20175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.bindLong(1, phoneticNameStyle);
20195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.bindLong(2, dataId);
20205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.execute();
20215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String sortKey = null;
20235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                if (phoneticName == null && company != null) {
20245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    int nameStyle = splitter.guessFullNameStyle(company);
20255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    nameStyle = splitter.getAdjustedFullNameStyle(nameStyle);
2026ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                    if (nameStyle == FullNameStyle.CHINESE ||
2027ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                            nameStyle == FullNameStyle.CJK ) {
2028ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                        sortKey = ContactLocaleUtils.getIntance()
2029ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                                .getSortKey(company, nameStyle);
20305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    }
20315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                }
20325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                if (sortKey == null) {
20345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    sortKey = company;
20355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                }
20365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                updateRawContact205(rawContactUpdate, rawContactId, company,
20385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        company, phoneticNameStyle, phoneticName, sortKey, sortKey);
20395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
20405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } finally {
20415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            cursor.close();
20425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
20435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
20445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void updateRawContact205(SQLiteStatement rawContactUpdate, long rawContactId,
20465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String displayName, String displayNameAlternative, int phoneticNameStyle,
20475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String phoneticName, String sortKeyPrimary, String sortKeyAlternative) {
20485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 1, displayName);
20495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 2, displayNameAlternative);
20505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 3, phoneticName);
20515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.bindLong(4, phoneticNameStyle);
20525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 5, sortKeyPrimary);
20535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 6, sortKeyAlternative);
20545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.bindLong(7, rawContactId);
20555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.execute();
20565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
20575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
2058f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov    private void upgrateToVersion206(SQLiteDatabase db) {
2059f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
2060f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                + " ADD " + RawContacts.NAME_VERIFIED + " INTEGER NOT NULL DEFAULT 0;");
2061f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov    }
2062f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov
206331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    private interface Organization300Query {
206431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String TABLE = Tables.DATA;
206531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
206631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String SELECTION = DataColumns.MIMETYPE_ID + "=?";
206731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
206831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String COLUMNS[] = {
206931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization._ID,
207031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.RAW_CONTACT_ID,
207131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.COMPANY,
207231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.TITLE
207331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        };
207431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
207531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int ID = 0;
207631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int RAW_CONTACT_ID = 1;
207731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int COMPANY = 2;
207831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int TITLE = 3;
207931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    }
208031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
208131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    /**
208231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     * Fix for the bug where name lookup records for organizations would get removed by
208331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     * unrelated updates of the data rows.
208431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     */
2085b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeToVersion300(SQLiteDatabase db) {
2086b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeType = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
2087b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeType == -1) {
208831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            return;
208931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
209031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
209131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        ContentValues values = new ContentValues();
209231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
209331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        // Find all data rows with the mime type "organization"
209431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        Cursor cursor = db.query(Organization300Query.TABLE, Organization300Query.COLUMNS,
2095b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Organization300Query.SELECTION, new String[] {String.valueOf(mimeType)},
209631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                null, null, null);
209731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        try {
209831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            while (cursor.moveToNext()) {
209931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                long dataId = cursor.getLong(Organization300Query.ID);
210031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                long rawContactId = cursor.getLong(Organization300Query.RAW_CONTACT_ID);
210131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                String company = cursor.getString(Organization300Query.COMPANY);
210231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                String title = cursor.getString(Organization300Query.TITLE);
210331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
210431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                // First delete name lookup if there is any (chances are there won't be)
210531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                db.delete(Tables.NAME_LOOKUP, NameLookupColumns.DATA_ID + "=?",
210631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                        new String[]{String.valueOf(dataId)});
210731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
210831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                // Now insert two name lookup records: one for company name, one for title
210931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.DATA_ID, dataId);
211031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
211131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.NAME_TYPE, NameLookupType.ORGANIZATION);
211231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
211331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                if (!TextUtils.isEmpty(company)) {
211431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME,
211531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                            NameNormalizer.normalize(company));
211631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
211731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                }
211831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
211931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                if (!TextUtils.isEmpty(title)) {
212031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME,
212131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                            NameNormalizer.normalize(title));
212231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
212331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                }
212431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            }
212531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        } finally {
212631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            cursor.close();
212731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
212831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    }
212931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
2130b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private static final class Upgrade303Query {
2131b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
2132b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2133b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String SELECTION =
2134b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=?" +
2135b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    " AND " + Data._ID + " NOT IN " +
2136b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    "(SELECT " + NameLookupColumns.DATA_ID + " FROM " + Tables.NAME_LOOKUP + ")" +
2137b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    " AND " + Data.DATA1 + " NOT NULL";
2138b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2139b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String COLUMNS[] = {
2140b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data._ID,
2141b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data.RAW_CONTACT_ID,
2142b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data.DATA1,
2143b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        };
2144b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2145b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int ID = 0;
2146b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
2147b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int DATA1 = 2;
2148b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2149b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2150b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    /**
2151b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * The {@link ContactsProvider2#update} method was deleting name lookup for new
2152b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * emails during the sync.  We need to restore the lost name lookup rows.
2153b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     */
2154b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeEmailToVersion303(SQLiteDatabase db) {
2155b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Email.CONTENT_ITEM_TYPE);
2156b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeTypeId == -1) {
2157b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return;
2158b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2159b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2160b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        ContentValues values = new ContentValues();
2161b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2162b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        // Find all data rows with the mime type "email" that are missing name lookup
2163b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Cursor cursor = db.query(Upgrade303Query.TABLE, Upgrade303Query.COLUMNS,
2164b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Upgrade303Query.SELECTION, new String[] {String.valueOf(mimeTypeId)},
2165b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                null, null, null);
2166b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2167b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            while (cursor.moveToNext()) {
2168b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long dataId = cursor.getLong(Upgrade303Query.ID);
2169b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long rawContactId = cursor.getLong(Upgrade303Query.RAW_CONTACT_ID);
2170b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                String value = cursor.getString(Upgrade303Query.DATA1);
2171b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                value = extractHandleFromEmailAddress(value);
2172b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2173b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                if (value != null) {
2174b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.DATA_ID, dataId);
2175b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
2176b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.NAME_TYPE, NameLookupType.EMAIL_BASED_NICKNAME);
2177b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME, NameNormalizer.normalize(value));
2178b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
2179b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                }
2180b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            }
2181b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } finally {
2182b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            cursor.close();
2183b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2184b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2185b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2186b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    /**
2187b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * The {@link ContactsProvider2#update} method was deleting name lookup for new
2188b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * nicknames during the sync.  We need to restore the lost name lookup rows.
2189b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     */
2190b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeNicknameToVersion303(SQLiteDatabase db) {
2191b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Nickname.CONTENT_ITEM_TYPE);
2192b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeTypeId == -1) {
2193b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return;
2194b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2195b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2196b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        ContentValues values = new ContentValues();
2197b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2198b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        // Find all data rows with the mime type "nickname" that are missing name lookup
2199b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Cursor cursor = db.query(Upgrade303Query.TABLE, Upgrade303Query.COLUMNS,
2200b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Upgrade303Query.SELECTION, new String[] {String.valueOf(mimeTypeId)},
2201b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                null, null, null);
2202b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2203b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            while (cursor.moveToNext()) {
2204b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long dataId = cursor.getLong(Upgrade303Query.ID);
2205b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long rawContactId = cursor.getLong(Upgrade303Query.RAW_CONTACT_ID);
2206b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                String value = cursor.getString(Upgrade303Query.DATA1);
2207b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2208b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.DATA_ID, dataId);
2209b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
2210b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.NAME_TYPE, NameLookupType.NICKNAME);
2211b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.NORMALIZED_NAME, NameNormalizer.normalize(value));
2212b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                db.insert(Tables.NAME_LOOKUP, null, values);
2213b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            }
2214b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } finally {
2215b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            cursor.close();
2216b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2217b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2218b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
221951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void upgradeToVersion304(SQLiteDatabase db) {
222051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        // Mimetype table requires an index on mime type
222151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS mime_type ON " + Tables.MIMETYPES + " (" +
222251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                MimetypesColumns.MIMETYPE +
222351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        ");");
222451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
222551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
222660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann    private void upgradeToVersion306(SQLiteDatabase db) {
222760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        // Fix invalid lookup that was used for Exchange contacts (it was not escaped)
222860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        // It happened when a new contact was created AND synchronized
222960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final StringBuilder lookupKeyBuilder = new StringBuilder();
223060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final SQLiteStatement updateStatement = db.compileStatement(
223160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "UPDATE contacts " +
223260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "SET lookup=? " +
223360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "WHERE _id=?");
223460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final Cursor contactIdCursor = db.rawQuery(
223560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "SELECT DISTINCT contact_id " +
223660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "FROM raw_contacts " +
223760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "WHERE deleted=0 AND account_type='com.android.exchange'",
223860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                null);
223960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        try {
224060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            while (contactIdCursor.moveToNext()) {
224160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                final long contactId = contactIdCursor.getLong(0);
224260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                lookupKeyBuilder.setLength(0);
224360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                final Cursor c = db.rawQuery(
224460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "SELECT account_type, account_name, _id, sourceid, display_name " +
224560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "FROM raw_contacts " +
224660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "WHERE contact_id=? " +
224760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "ORDER BY _id",
224860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        new String[] { String.valueOf(contactId) });
224960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                try {
225060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    while (c.moveToNext()) {
225160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        ContactLookupKey.appendToLookupKey(lookupKeyBuilder,
225260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(0),
225360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(1),
225460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getLong(2),
225560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(3),
225660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(4));
225760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    }
225860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                } finally {
225960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    c.close();
226060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                }
226160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
226260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                if (lookupKeyBuilder.length() == 0) {
226360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    updateStatement.bindNull(1);
226460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                } else {
226560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    updateStatement.bindString(1, Uri.encode(lookupKeyBuilder.toString()));
226660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                }
226760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                updateStatement.bindLong(2, contactId);
226860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
226960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                updateStatement.execute();
227060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            }
227160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        } finally {
227260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            updateStatement.close();
227360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            contactIdCursor.close();
227460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        }
227560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann    }
227660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
2277b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    private void upgradeToVersion307(SQLiteDatabase db) {
2278b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        db.execSQL("CREATE TABLE properties (" +
2279b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                "property_key TEXT PRIMARY_KEY, " +
2280b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                "property_value TEXT" +
2281b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ");");
2282b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
2283b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
2284743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov    private void upgradeToVersion308(SQLiteDatabase db) {
22854394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE accounts (" +
22864394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "account_name TEXT, " +
22874394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "account_type TEXT " +
22884394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
2289743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
22904394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO accounts " +
22914394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "SELECT DISTINCT account_name, account_type FROM raw_contacts");
2292743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov    }
2293743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
2294f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov    private void upgradeToVersion400(SQLiteDatabase db) {
2295dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        db.execSQL("ALTER TABLE " + Tables.GROUPS
2296dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + " ADD " + Groups.FAVORITES + " INTEGER NOT NULL DEFAULT 0;");
2297dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        db.execSQL("ALTER TABLE " + Tables.GROUPS
2298dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + " ADD " + Groups.AUTO_ADD + " INTEGER NOT NULL DEFAULT 0;");
2299dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana    }
2300dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana
23017da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov    private void upgradeToVersion353(SQLiteDatabase db) {
23027da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        db.execSQL("DELETE FROM contacts " +
23037da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov                "WHERE NOT EXISTS (SELECT 1 FROM raw_contacts WHERE contact_id=contacts._id)");
23047da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov    }
23057da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
230651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void rebuildNameLookup(SQLiteDatabase db) {
230751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
230851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        insertNameLookup(db);
230951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        createContactsIndexes(db);
231051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
231151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
231204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
231351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     * Regenerates all locale-sensitive data: nickname_lookup, name_lookup and sort keys.
231404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
231551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    public void setLocale(ContactsProvider2 provider, Locale locale) {
231651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        Log.i(TAG, "Switching to locale " + locale);
231704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
2318c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamilton        long start = SystemClock.uptimeMillis();
231951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
232051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.setLocale(locale);
232151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.beginTransaction();
232251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
232351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX raw_contact_sort_key1_index");
232451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX raw_contact_sort_key2_index");
232551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
232651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
232751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            loadNicknameLookupTable(db);
232851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertNameLookup(db);
232951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            rebuildSortKeys(db, provider);
233051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            createContactsIndexes(db);
233151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.setTransactionSuccessful();
233251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
233351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.endTransaction();
233451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
233551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
2336c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamilton        Log.i(TAG, "Locale change completed in " + (SystemClock.uptimeMillis() - start) + "ms");
233751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
233851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
233951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    /**
234051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     * Regenerates sort keys for all contacts.
234151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     */
234251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void rebuildSortKeys(SQLiteDatabase db, ContactsProvider2 provider) {
234351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        Cursor cursor = db.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID},
234451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                null, null, null, null, null);
234551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
234651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            while (cursor.moveToNext()) {
234751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                long rawContactId = cursor.getLong(0);
234851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                provider.updateRawContactDisplayName(db, rawContactId);
234951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            }
235051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
235151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            cursor.close();
235251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
235351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
235451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
235551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void insertNameLookup(SQLiteDatabase db) {
235604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NAME_LOOKUP);
235704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
235804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        SQLiteStatement nameLookupInsert = db.compileStatement(
235904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                "INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "("
236004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.RAW_CONTACT_ID + ","
236104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.DATA_ID + ","
236204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.NAME_TYPE + ","
236304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.NORMALIZED_NAME +
236404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                ") VALUES (?,?,?,?)");
236504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
236651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
236751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertStructuredNameLookup(db, nameLookupInsert);
236851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertOrganizationLookup(db, nameLookupInsert);
236951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertEmailLookup(db, nameLookupInsert);
237051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertNicknameLookup(db, nameLookupInsert);
237151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
237251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            nameLookupInsert.close();
237351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
237404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
237504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
237604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class StructuredNameQuery {
237704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
237804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
237904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
238004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
238104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
238204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
238304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName._ID,
238404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName.RAW_CONTACT_ID,
238504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName.DISPLAY_NAME,
238604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
238704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
238804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
238904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
239004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int DISPLAY_NAME = 2;
239104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
239204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
239304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private class StructuredNameLookupBuilder extends NameLookupBuilder {
239404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
239504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        private final SQLiteStatement mNameLookupInsert;
239604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        private final CommonNicknameCache mCommonNicknameCache;
239704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
239804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public StructuredNameLookupBuilder(NameSplitter splitter,
239904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                CommonNicknameCache commonNicknameCache, SQLiteStatement nameLookupInsert) {
240004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            super(splitter);
240104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            this.mCommonNicknameCache = commonNicknameCache;
240204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            this.mNameLookupInsert = nameLookupInsert;
240304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
240404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
240504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        @Override
240604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        protected void insertNameLookup(long rawContactId, long dataId, int lookupType,
240704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String name) {
240804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            if (!TextUtils.isEmpty(name)) {
240904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                ContactsDatabaseHelper.this.insertNormalizedNameLookup(mNameLookupInsert,
241004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        rawContactId, dataId, lookupType, name);
241104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
241204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
241304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
241404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        @Override
241504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        protected String[] getCommonNicknameClusters(String normalizedName) {
241604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return mCommonNicknameCache.getCommonNicknameClusters(normalizedName);
241704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
241804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
241904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
242004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
242104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all structured names in the database.
242204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
242304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertStructuredNameLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
2424d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov        NameSplitter nameSplitter = createNameSplitter();
2425d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov        NameLookupBuilder nameLookupBuilder = new StructuredNameLookupBuilder(nameSplitter,
242604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                new CommonNicknameCache(db), nameLookupInsert);
242704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, StructuredName.CONTENT_ITEM_TYPE);
242804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(StructuredNameQuery.TABLE, StructuredNameQuery.COLUMNS,
242904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredNameQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
243004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
243104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
243204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
243304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(StructuredNameQuery.ID);
243404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(StructuredNameQuery.RAW_CONTACT_ID);
243504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String name = cursor.getString(StructuredNameQuery.DISPLAY_NAME);
2436d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov                int fullNameStyle = nameSplitter.guessFullNameStyle(name);
243751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                fullNameStyle = nameSplitter.getAdjustedFullNameStyle(fullNameStyle);
2438d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov                nameLookupBuilder.insertNameLookup(rawContactId, dataId, name, fullNameStyle);
243904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
244004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
244104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
244204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
244304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
244404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
244504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class OrganizationQuery {
244604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
244704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
244804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
244904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
245004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
245104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
245204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization._ID,
245304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.RAW_CONTACT_ID,
245404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.COMPANY,
245504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.TITLE,
245604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
245704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
245804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
245904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
246004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int COMPANY = 2;
246104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int TITLE = 3;
246204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
246304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
246404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
246504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all organizations in the database.
246604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
246704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertOrganizationLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
246804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
246904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(OrganizationQuery.TABLE, OrganizationQuery.COLUMNS,
247004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                OrganizationQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
247104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
247204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
247304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
247404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(OrganizationQuery.ID);
247504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(OrganizationQuery.RAW_CONTACT_ID);
247604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String organization = cursor.getString(OrganizationQuery.COMPANY);
247704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String title = cursor.getString(OrganizationQuery.TITLE);
247804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
247904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.ORGANIZATION, organization);
248004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
248104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.ORGANIZATION, title);
248204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
248304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
248404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
248504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
248604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
248704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
248804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class EmailQuery {
248904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
249004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
249104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
249204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
249304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
249404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
249504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email._ID,
249604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email.RAW_CONTACT_ID,
249704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email.ADDRESS,
249804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
249904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
250004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
250104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
250204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ADDRESS = 2;
250304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
250404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
250504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
250604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all email addresses in the database.
250704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
250804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertEmailLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
250904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Email.CONTENT_ITEM_TYPE);
251004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(EmailQuery.TABLE, EmailQuery.COLUMNS,
251104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                EmailQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
251204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
251304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
251404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
251504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(EmailQuery.ID);
251604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(EmailQuery.RAW_CONTACT_ID);
251704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String address = cursor.getString(EmailQuery.ADDRESS);
251804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                address = extractHandleFromEmailAddress(address);
251904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
252004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.EMAIL_BASED_NICKNAME, address);
252104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
252204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
252304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
252404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
252504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
252604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
252704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class NicknameQuery {
252804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
252904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
253004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
253104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
253204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
253304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
253404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname._ID,
253504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname.RAW_CONTACT_ID,
253604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname.NAME,
253704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
253804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
253904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
254004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
254104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int NAME = 2;
254204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
254304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
254404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
254504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all nicknames in the database.
254604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
254704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertNicknameLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
254804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Nickname.CONTENT_ITEM_TYPE);
254904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(NicknameQuery.TABLE, NicknameQuery.COLUMNS,
255004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                NicknameQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
255104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
255204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
255304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
255404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(NicknameQuery.ID);
255504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(NicknameQuery.RAW_CONTACT_ID);
255604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String nickname = cursor.getString(NicknameQuery.NAME);
255704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
255804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.NICKNAME, nickname);
255904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
256004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
256104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
256204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
256304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
256404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
256504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
256604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts a record in the {@link Tables#NAME_LOOKUP} table.
256704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
256804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    public void insertNameLookup(SQLiteStatement stmt, long rawContactId, long dataId,
256904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            int lookupType, String name) {
257004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (TextUtils.isEmpty(name)) {
257104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return;
257204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
257304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
257404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        String normalized = NameNormalizer.normalize(name);
257504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (TextUtils.isEmpty(normalized)) {
257604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return;
257704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
257804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
257904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        insertNormalizedNameLookup(stmt, rawContactId, dataId, lookupType, normalized);
258004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
258104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
258204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertNormalizedNameLookup(SQLiteStatement stmt, long rawContactId, long dataId,
258304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            int lookupType, String normalizedName) {
258404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(1, rawContactId);
258504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(2, dataId);
258604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(3, lookupType);
258704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindString(4, normalizedName);
258804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.executeInsert();
258904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
259004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
25914394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    /**
25924394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov     * Changing the VISIBLE bit from a field on both RawContacts and Contacts to a separate table.
25934394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov     */
25944394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    private void upgradeToVersion401(SQLiteDatabase db) {
25954394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.VISIBLE_CONTACTS + " (" +
25964394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
25974394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
25984394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.VISIBLE_CONTACTS +
25994394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " SELECT " + Contacts._ID +
26004394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " FROM " + Tables.CONTACTS +
26014394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " WHERE " + Contacts.IN_VISIBLE_GROUP + "!=0");
26024394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("DROP INDEX contacts_visible_index");
26034394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    }
26044394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
2605d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    /**
2606d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov     * Introducing a new table: directories.
2607d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov     */
2608d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    private void upgradeToVersion402(SQLiteDatabase db) {
2609d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        createDirectoriesTable(db);
2610d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    }
2611d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
261297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    private void upgradeToVersion403(SQLiteDatabase db) {
261397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
261497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        createDirectoriesTable(db);
261597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
261697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("ALTER TABLE raw_contacts"
261797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + " ADD raw_contact_is_read_only INTEGER NOT NULL DEFAULT 0;");
261897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
261997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("ALTER TABLE data"
262097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + " ADD is_read_only INTEGER NOT NULL DEFAULT 0;");
262197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    }
262297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
2623892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    private void upgradeToVersion405(SQLiteDatabase db) {
2624892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS phone_lookup;");
2625892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        // Private phone numbers table used for lookup
2626892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" +
2627892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID
2628892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " INTEGER REFERENCES data(_id) NOT NULL," +
2629892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID
2630892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
2631892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL," +
2632892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL" +
2633892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2634892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2635892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" +
2636892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + "," +
2637892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
2638892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
2639892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2640892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2641892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
2642892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
2643892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
2644892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
2645892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2646892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2647892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Phone.CONTENT_ITEM_TYPE);
2648892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (mimeTypeId == -1) {
2649892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            return;
2650892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
2651892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2652892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        String mCountryIso = getCountryIso();
2653892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        Cursor cursor = db.rawQuery(
2654892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    "SELECT _id, " + Phone.RAW_CONTACT_ID + ", " + Phone.NUMBER +
2655892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    " FROM " + Tables.DATA +
2656892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId
2657892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                            + " AND " + Phone.NUMBER + " NOT NULL", null);
2658892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2659892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ContentValues phoneValues = new ContentValues();
2660892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        try {
2661892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            while (cursor.moveToNext()) {
2662892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                long dataID = cursor.getLong(0);
2663892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                long rawContactID = cursor.getLong(1);
2664892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String number = cursor.getString(2);
2665892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String numberE164 = PhoneNumberUtils.formatNumberToE164(number, mCountryIso);
2666892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String normalizedNumber = PhoneNumberUtils.normalizeNumber(number);
2667892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                if (!TextUtils.isEmpty(normalizedNumber)) {
2668892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.clear();
2669892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactID);
2670892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.DATA_ID, dataID);
2671892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber);
2672892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.MIN_MATCH,
2673892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                            PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber));
2674892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    db.insert(Tables.PHONE_LOOKUP, null, phoneValues);
2675892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2676892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    if (numberE164 != null && !numberE164.equals(normalizedNumber)) {
2677892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, numberE164);
2678892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        phoneValues.put(PhoneLookupColumns.MIN_MATCH,
2679892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                                PhoneNumberUtils.toCallerIDMinMatch(numberE164));
2680892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        db.insert(Tables.PHONE_LOOKUP, null, phoneValues);
2681892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    }
2682892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                }
2683892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
2684892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        } finally {
2685892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            cursor.close();
2686892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
2687892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    }
2688892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
26892530512f639c4979fd7371c7dd25dd67e8118124Bai Tao    private void upgradeToVersion406(SQLiteDatabase db) {
26902530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        db.execSQL("ALTER TABLE calls ADD countryiso TEXT;");
26912530512f639c4979fd7371c7dd25dd67e8118124Bai Tao    }
26922530512f639c4979fd7371c7dd25dd67e8118124Bai Tao
2693d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    private void upgradeToVersion409(SQLiteDatabase db) {
2694d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
2695d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        createDirectoriesTable(db);
2696d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    }
2697d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov
2698385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    /**
2699d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov     * Adding DEFAULT_DIRECTORY table.
2700385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     */
2701d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    private void upgradeToVersion411(SQLiteDatabase db) {
2702d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS " + Tables.DEFAULT_DIRECTORY);
2703385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DEFAULT_DIRECTORY + " (" +
2704385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
2705385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        ");");
2706385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2707385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // Process contacts without an account
2708385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
2709385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " SELECT " + RawContacts.CONTACT_ID +
2710385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS +
2711385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL " +
2712385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL ");
2713385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2714385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // Process accounts that don't have a default group (e.g. Exchange)
2715385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
2716385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " SELECT " + RawContacts.CONTACT_ID +
2717385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS +
2718385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE NOT EXISTS" +
2719385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " (SELECT " + Groups._ID +
2720385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "  FROM " + Tables.GROUPS +
2721385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
2722385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_NAME +
2723385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "    AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
2724385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
2725385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "    AND " + Groups.AUTO_ADD + " != 0" +
2726385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ")");
2727385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2728385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        long mimetype = lookupMimeTypeId(db, GroupMembership.CONTENT_ITEM_TYPE);
2729385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2730d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        // Process accounts that do have a default group (e.g. Google)
2731385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
2732385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " SELECT " + RawContacts.CONTACT_ID +
2733385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS +
2734385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " JOIN " + Tables.DATA +
2735385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "   ON (" + RawContactsColumns.CONCRETE_ID + "=" + Data.RAW_CONTACT_ID + ")" +
2736385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE " + DataColumns.MIMETYPE_ID + "=" + mimetype +
2737d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                " AND EXISTS" +
2738d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                " (SELECT " + Groups._ID +
2739d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "  FROM " + Tables.GROUPS +
2740d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
2741d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_NAME +
2742d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "    AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
2743d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
2744d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "    AND " + Groups.AUTO_ADD + " != 0" +
2745d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                ")");
27463d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
2747385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2748e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    private void upgradeToVersion413(SQLiteDatabase db) {
27493ea7932a47027c8629d3a301e1a16e7d2c8a298dDmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
27503ea7932a47027c8629d3a301e1a16e7d2c8a298dDmitri Plotnikov        createDirectoriesTable(db);
2751e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    }
2752e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov
2753c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov    private void upgradeToVersion415(SQLiteDatabase db) {
2754c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        db.execSQL(
2755c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "ALTER TABLE " + Tables.GROUPS +
2756c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                " ADD " + Groups.GROUP_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0");
2757c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        db.execSQL(
2758c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "UPDATE " + Tables.GROUPS +
2759c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "   SET " + Groups.GROUP_IS_READ_ONLY + "=1" +
2760c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                " WHERE " + Groups.SYSTEM_ID + " NOT NULL");
2761c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov    }
2762c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov
2763b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    public String extractHandleFromEmailAddress(String email) {
2764b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email);
2765b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (tokens.length == 0) {
2766b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return null;
2767b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2768b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2769b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        String address = tokens[0].getAddress();
2770b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        int at = address.indexOf('@');
2771b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (at != -1) {
2772b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return address.substring(0, at);
2773b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2774b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        return null;
2775b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2776b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
277708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov    public String extractAddressFromEmailAddress(String email) {
277808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email);
277908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        if (tokens.length == 0) {
278008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            return null;
278108768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        }
278208768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
278308768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        return tokens[0].getAddress();
278408768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov    }
278508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
2786b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private long lookupMimeTypeId(SQLiteDatabase db, String mimeType) {
2787b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2788b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return DatabaseUtils.longForQuery(db,
2789b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    "SELECT " + MimetypesColumns._ID +
2790b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    " FROM " + Tables.MIMETYPES +
2791b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    " WHERE " + MimetypesColumns.MIMETYPE
2792b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                            + "='" + mimeType + "'", null);
2793b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } catch (SQLiteDoneException e) {
2794b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            // No rows of this type in the database
2795b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return -1;
2796b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2797b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2798b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
27995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void bindString(SQLiteStatement stmt, int index, String value) {
28005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (value == null) {
28015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            stmt.bindNull(index);
28025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } else {
28035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            stmt.bindString(index, value);
28045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
28055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
28065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
2807a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    /**
2808f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * Adds index stats into the SQLite database to force it to always use the lookup indexes.
2809f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     */
2810f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    private void updateSqliteStats(SQLiteDatabase db) {
2811f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2812f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        // Specific stats strings are based on an actual large database after running ANALYZE
2813f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        try {
28148fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.CONTACTS,
28158fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "contacts_restricted_index", "10000 9000");
28168fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.CONTACTS,
28178fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "contacts_has_phone_index", "10000 500");
28188fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
28198fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.RAW_CONTACTS,
28208fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "raw_contacts_source_id_index", "10000 1 1 1");
28218fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.RAW_CONTACTS,
28228fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "raw_contacts_contact_id_index", "10000 2");
28238fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
28248fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
28258fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "name_lookup_raw_contact_id_index", "10000 3");
28268fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
2827916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                    "name_lookup_index", "10000 3 2 2 1");
28288fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
28298fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "sqlite_autoindex_name_lookup_1", "10000 3 2 1");
28308fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
28318fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.PHONE_LOOKUP,
28328fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "phone_lookup_index", "10000 2 2 1");
283336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            updateIndexStats(db, Tables.PHONE_LOOKUP,
283436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    "phone_lookup_min_match_index", "10000 2 2 1");
28358fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
28368fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.DATA,
28378fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "data_mimetype_data1_index", "60000 5000 2");
28388fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.DATA,
28398fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "data_raw_contact_id", "60000 10");
28408fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
28418fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.GROUPS,
28428fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "groups_source_id_index", "50 1 1 1");
28438fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
28448fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NICKNAME_LOOKUP,
28458fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "sqlite_autoindex_name_lookup_1", "500 2 1");
28468fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
2847f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        } catch (SQLException e) {
2848f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            Log.e(TAG, "Could not update index stats", e);
2849f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        }
2850f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2851f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2852f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    /**
2853f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * Stores statistics for a given index.
2854f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     *
2855f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * @param stats has the following structure: the first index is the expected size of
2856f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * the table.  The following integer(s) are the expected number of records selected with the
2857f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * index.  There should be one integer per indexed column.
2858f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     */
28595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void updateIndexStats(SQLiteDatabase db, String table, String index,
28605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String stats) {
2861f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        db.execSQL("DELETE FROM sqlite_stat1 WHERE tbl='" + table + "' AND idx='" + index + "';");
2862f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        db.execSQL("INSERT INTO sqlite_stat1 (tbl,idx,stat)"
2863f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                + " VALUES ('" + table + "','" + index + "','" + stats + "');");
2864f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2865f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2866f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    @Override
2867f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    public synchronized SQLiteDatabase getWritableDatabase() {
2868f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        SQLiteDatabase db = super.getWritableDatabase();
2869f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        if (mReopenDatabase) {
2870f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            mReopenDatabase = false;
2871f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            close();
2872f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            db = super.getWritableDatabase();
2873f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        }
2874f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        return db;
2875f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2876f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2877f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    /**
2878a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov     * Wipes all data except mime type and package lookup tables.
2879a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov     */
2880a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    public void wipeData() {
2881a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
28823d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov
288333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.ACCOUNTS + ";");
288469cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " VALUES(NULL, NULL)");
288533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov
2886d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CONTACTS + ";");
28875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.RAW_CONTACTS + ";");
2888a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.DATA + ";");
2889a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.PHONE_LOOKUP + ";");
2890a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NAME_LOOKUP + ";");
2891ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("DELETE FROM " + Tables.GROUPS + ";");
2892b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.AGGREGATION_EXCEPTIONS + ";");
2893eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        db.execSQL("DELETE FROM " + Tables.SETTINGS + ";");
2894a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.ACTIVITIES + ";");
28953d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CALLS + ";");
289672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.DIRECTORIES + ";");
289772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov
2898b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        // Note: we are not removing reference data from Tables.NICKNAME_LOOKUP
2899a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
2900b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
290104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    public NameSplitter createNameSplitter() {
290204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        return new NameSplitter(
290304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_prefixes),
290404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_last_name_prefixes),
290504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_suffixes),
290604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_conjunctions),
290704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Locale.getDefault());
290804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
290904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
2910b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
2911619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey     * Return the {@link ApplicationInfo#uid} for the given package name.
2912619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey     */
2913619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    public static int getUidForPackageName(PackageManager pm, String packageName) {
2914619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        try {
2915619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            ApplicationInfo clientInfo = pm.getApplicationInfo(packageName, 0 /* no flags */);
2916619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            return clientInfo.uid;
2917619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        } catch (NameNotFoundException e) {
2918619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            throw new RuntimeException(e);
2919619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        }
2920619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
2921619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
2922619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    /**
2923b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Perform an internal string-to-integer lookup using the compiled
2924b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * {@link SQLiteStatement} provided, using the in-memory cache to speed up
2925b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups. If a mapping isn't found in cache or database, it will be
2926b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * created. All new, uncached answers are added to the cache automatically.
2927b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *
2928b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param query Compiled statement used to query for the mapping.
2929b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param insert Compiled statement used to insert a new mapping when no
2930b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *            existing one is found in cache or from query.
2931b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param value Value to find mapping for.
2932b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param cache In-memory cache of previous answers.
2933b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @return An unique integer mapping for the given value.
2934b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
2935f4a3b7e523e36679b68edd2af632e26648758ff2Dmitri Plotnikov    private long getCachedId(SQLiteStatement query, SQLiteStatement insert,
2936b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String value, HashMap<String, Long> cache) {
2937b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Try an in-memory cache lookup
2938b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (cache.containsKey(value)) {
2939b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return cache.get(value);
2940b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
2941b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
2942b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        long id = -1;
2943b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
2944b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try searching database for mapping
2945b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(query, 1, value);
2946b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            id = query.simpleQueryForLong();
2947b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
2948b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Nothing found, so try inserting new mapping
2949b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(insert, 1, value);
2950b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            id = insert.executeInsert();
2951b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
2952b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
2953b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (id != -1) {
2954b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Cache and return the new answer
2955b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            cache.put(value, id);
2956b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return id;
2957b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } else {
2958b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Otherwise throw if no mapping found or created
2959b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            throw new IllegalStateException("Couldn't find or create internal "
2960b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                    + "lookup table entry for value " + value);
2961b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
2962b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
2963b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
2964b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
2965ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Convert a package name into an integer, using {@link Tables#PACKAGES} for
2966b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
2967b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
2968b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getPackageId(String packageName) {
2969b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
2970b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
2971b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return getCachedId(mPackageQuery, mPackageInsert, packageName, mPackageCache);
2972b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
2973b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
2974b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
2975ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Convert a mimetype into an integer, using {@link Tables#MIMETYPES} for
2976b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
2977b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
2978b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getMimeTypeId(String mimetype) {
2979b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
2980b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
29815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        return getMimeTypeIdNoDbCheck(mimetype);
29825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
29835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
29845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private long getMimeTypeIdNoDbCheck(String mimetype) {
2985b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return getCachedId(mMimetypeQuery, mMimetypeInsert, mimetype, mMimetypeCache);
2986b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
2987b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
2988b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
2989ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Find the mimetype for the given {@link Data#_ID}.
2990b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
2991b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getDataMimeType(long dataId) {
2992b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
2993b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
2994b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
2995b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
2996b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mDataMimetypeQuery, 1, dataId);
2997b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mDataMimetypeQuery.simpleQueryForString();
2998b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
2999b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
3000b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
3001b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
3002b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3003b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3004b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3005b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3006b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Find the mime-type for the given {@link Activities#_ID}.
3007b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3008b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getActivityMimeType(long activityId) {
3009b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
3010b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
3011b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
3012b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
3013b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mActivitiesMimetypeQuery, 1, activityId);
3014b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mActivitiesMimetypeQuery.simpleQueryForString();
3015b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
3016b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
3017b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
3018b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
3019b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3020b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
30216bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov
30226bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov    /**
3023d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Update {@link Contacts#IN_VISIBLE_GROUP} for all contacts.
3024ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     */
3025ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public void updateAllVisible() {
3026385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        updateCustomContactVisibility(getWritableDatabase(), "");
3027ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
3028ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
3029ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    /**
3030385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     * Update {@link Contacts#IN_VISIBLE_GROUP} and
3031385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     * {@link Tables#DEFAULT_DIRECTORY} for a specific contact.
3032ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     */
3033fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov    public void updateContactVisible(long contactId) {
30344394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
3035385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        updateCustomContactVisibility(getWritableDatabase(),
3036385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " AND " + Contacts._ID + "=" + contactId);
3037385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3038385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        String contactIdAsString = String.valueOf(contactId);
3039385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        long mimetype = getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
3040385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3041385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // The contact will be included in the default directory if contains
3042d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        // a raw contact that is in any group or in an account that
3043385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // does not have any AUTO_ADD groups.
3044385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        long visibleRawContact = DatabaseUtils.longForQuery(db,
3045385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "SELECT EXISTS (" +
3046385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts.CONTACT_ID +
3047385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3048385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " JOIN " + Tables.DATA +
3049385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   ON (" + RawContactsColumns.CONCRETE_ID + "="
3050385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                            + Data.RAW_CONTACT_ID + ")" +
3051385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3052385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + DataColumns.MIMETYPE_ID + "=?" +
3053385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ") OR EXISTS (" +
3054385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts._ID +
3055385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3056385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3057385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND NOT EXISTS" +
3058385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        " (SELECT " + Groups._ID +
3059385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  FROM " + Tables.GROUPS +
3060385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
3061385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                                + GroupsColumns.CONCRETE_ACCOUNT_NAME +
3062385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
3063385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                                + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
3064385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  AND " + Groups.AUTO_ADD + " != 0" +
3065385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        ")" +
3066385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ") OR EXISTS (" +
3067385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts._ID +
3068385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3069385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3070385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL " +
3071385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL" +
3072385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ")",
3073385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                new String[] {
3074385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    contactIdAsString,
30756c47e208236a62c55f396116e087331e05e148f3Dmitri Plotnikov                    String.valueOf(mimetype),
3076385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    contactIdAsString,
30776c47e208236a62c55f396116e087331e05e148f3Dmitri Plotnikov                    contactIdAsString
3078385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                });
3079385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3080385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        if (visibleRawContact != 0) {
3081385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY + " VALUES(?)",
3082385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    new String[] { contactIdAsString });
3083385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        } else {
3084385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            db.execSQL("DELETE FROM " + Tables.DEFAULT_DIRECTORY + " WHERE " + Contacts._ID + "=?",
3085385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    new String[] { contactIdAsString });
3086385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        }
3087385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    }
30884394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
3089385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    private void updateCustomContactVisibility(SQLiteDatabase db, String selection) {
3090ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        final long groupMembershipMimetypeId = getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
30914394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        String[] selectionArgs = new String[]{String.valueOf(groupMembershipMimetypeId)};
30924394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
30934394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // First delete what needs to be deleted, then insert what needs to be added.
30944394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // Since flash writes are very expensive, this approach is much better than
30954394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // delete-all-insert-all.
30964394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.VISIBLE_CONTACTS +
30974394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " WHERE " + "_id NOT IN" +
30984394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        "(SELECT " + Contacts._ID +
30994394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        " FROM " + Tables.CONTACTS +
31004394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        " WHERE (" + Clauses.CONTACT_IS_VISIBLE + ")=1) " + selection,
31014394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                selectionArgs);
3102fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
31034394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.VISIBLE_CONTACTS +
31044394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " SELECT " + Contacts._ID +
31054394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " FROM " + Tables.CONTACTS +
31064394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " WHERE " + Contacts._ID +
31074394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " NOT IN " + Tables.VISIBLE_CONTACTS +
31084394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                           " AND (" + Clauses.CONTACT_IS_VISIBLE + ")=1 " + selection,
31094394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                selectionArgs);
3110ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
3111ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
3112ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    /**
3113d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Returns contact ID for the given contact or zero if it is NULL.
31146bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov     */
3115d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    public long getContactId(long rawContactId) {
31166bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        getReadableDatabase();
31176bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        try {
3118d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov            DatabaseUtils.bindObjectToProgram(mContactIdQuery, 1, rawContactId);
3119d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov            return mContactIdQuery.simpleQueryForLong();
31206bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        } catch (SQLiteDoneException e) {
3121a3bd0246ca3741877488bca7aadd91c79b2fd8d2Fred Quintana            // No valid mapping found, so return 0
31226bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov            return 0;
31236bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        }
31246bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov    }
312561bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov
31265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov    public int getAggregationMode(long rawContactId) {
3127f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        getReadableDatabase();
3128f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        try {
31295ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov            DatabaseUtils.bindObjectToProgram(mAggregationModeQuery, 1, rawContactId);
3130f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            return (int)mAggregationModeQuery.simpleQueryForLong();
3131f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        } catch (SQLiteDoneException e) {
31326cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov            // No valid row found, so return "disabled"
31336cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov            return RawContacts.AGGREGATION_MODE_DISABLED;
3134f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3135f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3136f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
3137892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    public void buildPhoneLookupAndContactQuery(
3138892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            SQLiteQueryBuilder qb, String normalizedNumber, String numberE164) {
3139892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        String minMatch = PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber);
3140e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        StringBuilder sb = new StringBuilder();
314136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        appendPhoneLookupTables(sb, minMatch, true);
3142e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        qb.setTables(sb.toString());
3143e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
3144e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb = new StringBuilder();
3145892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        appendPhoneLookupSelection(sb, normalizedNumber, numberE164);
3146e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        qb.appendWhere(sb.toString());
3147bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    }
3148bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
3149e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    public String buildPhoneLookupAsNestedQuery(String number) {
3150e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        StringBuilder sb = new StringBuilder();
315136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        final String minMatch = PhoneNumberUtils.toCallerIDMinMatch(number);
3152e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append("(SELECT DISTINCT raw_contact_id" + " FROM ");
315336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        appendPhoneLookupTables(sb, minMatch, false);
3154e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(" WHERE ");
3155892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        appendPhoneLookupSelection(sb, number, null);
3156e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(")");
3157e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        return sb.toString();
3158e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    }
3159e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
316036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    private void appendPhoneLookupTables(StringBuilder sb, final String minMatch,
3161e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov            boolean joinContacts) {
3162e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(Tables.RAW_CONTACTS);
3163e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        if (joinContacts) {
3164fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov            sb.append(" JOIN " + getContactView() + " contacts_view"
3165fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                    + " ON (contacts_view._id = raw_contacts.contact_id)");
3166e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        }
3167892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        sb.append(", (SELECT data_id, normalized_number, length(normalized_number) as len "
3168892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " FROM phone_lookup " + " WHERE (" + Tables.PHONE_LOOKUP + "."
3169892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + PhoneLookupColumns.MIN_MATCH + " = '");
317036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        sb.append(minMatch);
317136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        sb.append("')) AS lookup, " + Tables.DATA);
3172e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    }
3173e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
3174892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    private void appendPhoneLookupSelection(StringBuilder sb, String number, String numberE164) {
3175892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        sb.append("lookup.data_id=data._id AND data.raw_contact_id=raw_contacts._id");
3176892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        boolean hasNumberE164 = !TextUtils.isEmpty(numberE164);
3177892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        boolean hasNumber = !TextUtils.isEmpty(number);
3178892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (hasNumberE164 || hasNumber) {
3179892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            sb.append(" AND ( ");
3180892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumberE164) {
3181892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" lookup.normalized_number = ");
3182892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                DatabaseUtils.appendEscapedSQLString(sb, numberE164);
3183892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3184892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumberE164 && hasNumber) {
3185892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" OR ");
3186892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3187892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumber) {
3188892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                int numberLen = number.length();
3189892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" lookup.len <= ");
3190892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(numberLen);
3191892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" AND substr(");
3192892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                DatabaseUtils.appendEscapedSQLString(sb, number);
3193892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(',');
3194892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(numberLen);
3195892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" - lookup.len + 1) = lookup.normalized_number");
3196892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3197892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            sb.append(')');
3198892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
319936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    }
320036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
320136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    public String getUseStrictPhoneNumberComparisonParameter() {
320236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        return mUseStrictPhoneNumberComparison ? "1" : "0";
3203fb362d1a5df250a49fad06db323b0d41fe0e3757Dmitri Plotnikov    }
3204bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
3205619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    /**
3206b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     * Loads common nickname mappings into the database.
3207b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     */
3208b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private void loadNicknameLookupTable(SQLiteDatabase db) {
320951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NICKNAME_LOOKUP);
321051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
321128f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar        String[] strings = mContext.getResources().getStringArray(
321228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar                com.android.internal.R.array.common_nicknames);
3213b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        if (strings == null || strings.length == 0) {
3214b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            return;
3215b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
3216b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
3217b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        SQLiteStatement nicknameLookupInsert = db.compileStatement("INSERT INTO "
3218b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                + Tables.NICKNAME_LOOKUP + "(" + NicknameLookupColumns.NAME + ","
3219b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                + NicknameLookupColumns.CLUSTER + ") VALUES (?,?)");
3220b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
322151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
322251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            for (int clusterId = 0; clusterId < strings.length; clusterId++) {
322351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                String[] names = strings[clusterId].split(",");
322451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                for (int j = 0; j < names.length; j++) {
322551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    String name = NameNormalizer.normalize(names[j]);
322651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    try {
322751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        DatabaseUtils.bindObjectToProgram(nicknameLookupInsert, 1, name);
322851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        DatabaseUtils.bindObjectToProgram(nicknameLookupInsert, 2,
322951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                                String.valueOf(clusterId));
323051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        nicknameLookupInsert.executeInsert();
323151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    } catch (SQLiteException e) {
323251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
323351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        // Print the exception and keep going - this is not a fatal error
323451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        Log.e(TAG, "Cannot insert nickname: " + names[j], e);
323551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    }
3236b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                }
3237b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            }
323851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
323951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            nicknameLookupInsert.close();
3240b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
3241b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    }
3242b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
3243f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    public static void copyStringValue(ContentValues toValues, String toKey,
3244f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            ContentValues fromValues, String fromKey) {
3245f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        if (fromValues.containsKey(fromKey)) {
3246f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            toValues.put(toKey, fromValues.getAsString(fromKey));
3247f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3248f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3249f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
3250f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    public static void copyLongValue(ContentValues toValues, String toKey,
3251f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            ContentValues fromValues, String fromKey) {
3252f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        if (fromValues.containsKey(fromKey)) {
3253f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            long longValue;
3254f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            Object value = fromValues.get(fromKey);
3255f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            if (value instanceof Boolean) {
3256f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                if ((Boolean)value) {
3257f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                    longValue = 1;
3258f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                } else {
3259f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                    longValue = 0;
3260f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                }
32611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov            } else if (value instanceof String) {
32621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov                longValue = Long.parseLong((String)value);
3263f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            } else {
32641b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov                longValue = ((Number)value).longValue();
3265f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            }
3266f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            toValues.put(toKey, longValue);
3267f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3268f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3269f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
327035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    public SyncStateContentProviderHelper getSyncState() {
327135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        return mSyncState;
327235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    }
3273c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3274c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    /**
3275c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     * Delete the aggregate contact if it has no constituent raw contacts other
3276c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     * than the supplied one.
3277c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     */
3278c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    public void removeContactIfSingleton(long rawContactId) {
3279c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
3280c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3281c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        // Obtain contact ID from the supplied raw contact ID
3282c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        String contactIdFromRawContactId = "(SELECT " + RawContacts.CONTACT_ID + " FROM "
3283c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=" + rawContactId + ")";
3284c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3285c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        // Find other raw contacts in the same aggregate contact
3286c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        String otherRawContacts = "(SELECT contacts1." + RawContacts._ID + " FROM "
3287c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + Tables.RAW_CONTACTS + " contacts1 JOIN " + Tables.RAW_CONTACTS + " contacts2 ON ("
3288c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "contacts1." + RawContacts.CONTACT_ID + "=contacts2." + RawContacts.CONTACT_ID
3289c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + ") WHERE contacts1." + RawContacts._ID + "!=" + rawContactId + ""
3290c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " AND contacts2." + RawContacts._ID + "=" + rawContactId + ")";
3291c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3292c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CONTACTS
3293c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " WHERE " + Contacts._ID + "=" + contactIdFromRawContactId
3294c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " AND NOT EXISTS " + otherRawContacts + ";");
3295c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    }
32964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
32974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    /**
3298b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     * Returns the value from the {@link Tables#PROPERTIES} table.
3299b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     */
3300b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public String getProperty(String key, String defaultValue) {
3301b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        Cursor cursor = getReadableDatabase().query(Tables.PROPERTIES,
3302b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                new String[]{PropertiesColumns.PROPERTY_VALUE},
3303b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_KEY + "=?",
3304b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                new String[]{key}, null, null, null);
3305b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        String value = null;
3306b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        try {
3307b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            if (cursor.moveToFirst()) {
3308b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                value = cursor.getString(0);
3309b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            }
3310b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        } finally {
3311b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            cursor.close();
3312b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        }
3313b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3314b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        return value != null ? value : defaultValue;
3315b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
3316b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3317b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    /**
3318b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     * Stores a key-value pair in the {@link Tables#PROPERTIES} table.
3319b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     */
3320b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public void setProperty(String key, String value) {
33213d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        setProperty(getWritableDatabase(), key, value);
33223d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
33233d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
33243d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    private void setProperty(SQLiteDatabase db, String key, String value) {
3325b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ContentValues values = new ContentValues();
3326b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        values.put(PropertiesColumns.PROPERTY_KEY, key);
3327b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        values.put(PropertiesColumns.PROPERTY_VALUE, value);
33283d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        db.replace(Tables.PROPERTIES, null, values);
3329b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
3330b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3331b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    /**
33324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     * Check if {@link Binder#getCallingUid()} should be allowed access to
33334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     * {@link RawContacts#IS_RESTRICTED} data.
33344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     */
3335d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    boolean hasAccessToRestrictedData() {
33364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        final PackageManager pm = mContext.getPackageManager();
33376ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        int caller = Binder.getCallingUid();
33386ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        if (caller == 0) return true; // root can do anything
33396ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        final String[] callerPackages = pm.getPackagesForUid(caller);
33404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
33414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        // Has restricted access if caller matches any packages
33424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        for (String callerPackage : callerPackages) {
3343d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton            if (hasAccessToRestrictedData(callerPackage)) {
3344763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                return true;
3345763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar            }
3346763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        }
3347763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return false;
3348763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    }
3349763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar
3350763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    /**
3351763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     * Check if requestingPackage should be allowed access to
3352763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     * {@link RawContacts#IS_RESTRICTED} data.
3353763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     */
3354d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    boolean hasAccessToRestrictedData(String requestingPackage) {
3355d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        if (mUnrestrictedPackages != null) {
3356d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton            for (String allowedPackage : mUnrestrictedPackages) {
3357d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                if (allowedPackage.equals(requestingPackage)) {
3358d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                    return true;
3359d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                }
33604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov            }
33614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        }
33624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        return false;
33634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
33644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
33654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getDataView() {
3366d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa        return getDataView(false);
3367d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3368d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3369d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    public String getDataView(boolean requireRestrictedView) {
3370d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3371d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa                Views.DATA_ALL : Views.DATA_RESTRICTED;
33724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
33734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
33744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getRawContactView() {
3375763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return getRawContactView(false);
3376763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    }
3377763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar
3378763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    public String getRawContactView(boolean requireRestrictedView) {
3379d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3380763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                Views.RAW_CONTACTS_ALL : Views.RAW_CONTACTS_RESTRICTED;
33814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
33824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
33834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getContactView() {
3384763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return getContactView(false);
33854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
33864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
3387763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    public String getContactView(boolean requireRestrictedView) {
3388d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3389763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                Views.CONTACTS_ALL : Views.CONTACTS_RESTRICTED;
3390f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey    }
3391f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey
339289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov    public String getGroupView() {
339389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        return Views.GROUPS_ALL;
339489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov    }
339589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
3396a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getRawEntitiesView() {
3397a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return getRawEntitiesView(false);
3398a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    }
3399a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
3400a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getRawEntitiesView(boolean requireRestrictedView) {
3401a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3402a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                Views.RAW_ENTITIES : Views.RAW_ENTITIES_RESTRICTED;
3403a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    }
3404a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
3405a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getEntitiesView() {
3406a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return getEntitiesView(false);
3407d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3408d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3409a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getEntitiesView(boolean requireRestrictedView) {
3410d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3411a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                Views.ENTITIES : Views.ENTITIES_RESTRICTED;
3412d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3413d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3414ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov    /**
3415ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov     * Test if any of the columns appear in the given projection.
3416ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov     */
3417ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov    public boolean isInProjection(String[] projection, String... columns) {
341882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        if (projection == null) {
341982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            return true;
342082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        }
3421ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov
342282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        // Optimized for a single-column test
342382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        if (columns.length == 1) {
342482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            String column = columns[0];
342582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            for (String test : projection) {
342682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                if (column.equals(test)) {
342782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                    return true;
342882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                }
342982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            }
343082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        } else {
343182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            for (String test : projection) {
343282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                for (String column : columns) {
3433ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                    if (column.equals(test)) {
3434ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                        return true;
3435ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                    }
3436ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                }
3437ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov            }
3438ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov        }
3439ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov        return false;
34404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
3441fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3442fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    /**
3443fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * Returns a detailed exception message for the supplied URI.  It includes the calling
3444fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * user and calling package(s).
3445fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     */
3446fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    public String exceptionMessage(Uri uri) {
3447fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        return exceptionMessage(null, uri);
3448fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    }
3449fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3450fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    /**
3451fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * Returns a detailed exception message for the supplied URI.  It includes the calling
3452fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * user and calling package(s).
3453fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     */
3454fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    public String exceptionMessage(String message, Uri uri) {
3455fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        StringBuilder sb = new StringBuilder();
3456fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (message != null) {
3457fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(message).append("; ");
3458fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3459fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        sb.append("URI: ").append(uri);
3460fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        final PackageManager pm = mContext.getPackageManager();
3461fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        int callingUid = Binder.getCallingUid();
3462fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        sb.append(", calling user: ");
3463fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        String userName = pm.getNameForUid(callingUid);
3464fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (userName != null) {
3465fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(userName);
3466fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        } else {
3467fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(callingUid);
3468fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3469fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3470fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        final String[] callerPackages = pm.getPackagesForUid(callingUid);
3471fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (callerPackages != null && callerPackages.length > 0) {
3472fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            if (callerPackages.length == 1) {
3473fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(", calling package:");
3474fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(callerPackages[0]);
3475fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            } else {
3476fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(", calling package is one of: [");
3477fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                for (int i = 0; i < callerPackages.length; i++) {
3478fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    if (i != 0) {
3479fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                        sb.append(", ");
3480fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    }
3481fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    sb.append(callerPackages[i]);
3482fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                }
3483fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append("]");
3484fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            }
3485fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3486fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3487fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        return sb.toString();
3488fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    }
3489892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
3490892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    protected String getCountryIso() {
3491892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        CountryDetector detector =
3492892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            (CountryDetector) mContext.getSystemService(Context.COUNTRY_DETECTOR);
3493892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        return detector.detectCountry().getCountryIso();
3494892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    }
3495b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey}
3496