ContactsDatabaseHelper.java revision 5df7e46835c4f103b05407660b4769edd515760f
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;
20e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
2167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
2282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.content.ContentResolver;
23619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.ContentValues;
24b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.content.Context;
25619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.ApplicationInfo;
26619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.PackageManager;
27619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
28d91272b48f97243533c6580981e12a4847b5783fJeff Hamiltonimport android.content.res.Resources;
2936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikovimport android.database.Cursor;
30b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.DatabaseUtils;
31f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikovimport android.database.SQLException;
3278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException;
33b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteDatabase;
34b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteDoneException;
35b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikovimport android.database.sqlite.SQLiteException;
36b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteOpenHelper;
37bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikovimport android.database.sqlite.SQLiteQueryBuilder;
38b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteStatement;
39892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikovimport android.location.CountryDetector;
40fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikovimport android.net.Uri;
414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikovimport android.os.Binder;
42a3bd0246ca3741877488bca7aadd91c79b2fd8d2Fred Quintanaimport android.os.Bundle;
43c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamiltonimport android.os.SystemClock;
44b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.provider.BaseColumns;
45e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.provider.CallLog.Calls;
46a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract;
47b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions;
48a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email;
49a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.GroupMembership;
502a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im;
51a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname;
52a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization;
53a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone;
54a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName;
55d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.Contacts;
563d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikovimport android.provider.ContactsContract.Contacts.Photo;
57de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.Data;
58d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.provider.ContactsContract.Directory;
595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.DisplayNameSources;
605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.FullNameStyle;
61ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.Groups;
62d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts;
63eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkeyimport android.provider.ContactsContract.Settings;
6482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates;
6567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.SocialContract.Activities;
66bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikovimport android.telephony.PhoneNumberUtils;
6736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikovimport android.text.TextUtils;
68b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikovimport android.text.util.Rfc822Token;
69b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikovimport android.text.util.Rfc822Tokenizer;
70b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.util.Log;
71b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
72b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport java.util.HashMap;
735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport java.util.Locale;
74b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
75b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey/**
76b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov * Database helper for contacts. Designed as a singleton to make sure that all
77b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov * {@link android.content.ContentProvider} users get the same reference.
78b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov * Provides handy methods for maintaining package and mime-type lookup tables.
79b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey */
80b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov/* package */ class ContactsDatabaseHelper extends SQLiteOpenHelper {
81b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    private static final String TAG = "ContactsDatabaseHelper";
82b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
8397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    /**
8494c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov     * Contacts DB version ranges:
8597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     * <pre>
8697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   0-98    Cupcake/Donut
8797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   100-199 Eclair
8897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   200-299 Eclair-MR1
8997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   300-349 Froyo
9097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   350-399 Gingerbread
9197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   400-499 Honeycomb
9297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     * </pre>
9397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     */
94c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov    static final int DATABASE_VERSION = 415;
95e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
96b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private static final String DATABASE_NAME = "contacts2.db";
971f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    private static final String DATABASE_PRESENCE = "presence_db";
98b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
99b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface Tables {
100d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONTACTS = "contacts";
1015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACTS = "raw_contacts";
102ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String PACKAGES = "packages";
103ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String MIMETYPES = "mimetypes";
104b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PHONE_LOOKUP = "phone_lookup";
105a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NAME_LOOKUP = "name_lookup";
106b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        public static final String AGGREGATION_EXCEPTIONS = "agg_exceptions";
107eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        public static final String SETTINGS = "settings";
108b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA = "data";
109ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String GROUPS = "groups";
1101f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        public static final String PRESENCE = "presence";
111e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        public static final String AGGREGATED_PRESENCE = "agg_presence";
112b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String NICKNAME_LOOKUP = "nickname_lookup";
113e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        public static final String CALLS = "calls";
114a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        public static final String STATUS_UPDATES = "status_updates";
115b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        public static final String PROPERTIES = "properties";
116743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        public static final String ACCOUNTS = "accounts";
1174394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        public static final String VISIBLE_CONTACTS = "visible_contacts";
118d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        public static final String DIRECTORIES = "directories";
119385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        public static final String DEFAULT_DIRECTORY = "default_directory";
120b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
121ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String DATA_JOIN_MIMETYPES = "data "
1221b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id)";
123b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
12411944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        public static final String DATA_JOIN_RAW_CONTACTS = "data "
1258e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id)";
12611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
1275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String DATA_JOIN_MIMETYPE_RAW_CONTACTS = "data "
128c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
129c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id)";
130bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
131e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        // NOTE: This requires late binding of GroupMembership MIME-type
132e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String RAW_CONTACTS_JOIN_SETTINGS_DATA_GROUPS = "raw_contacts "
133e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN settings ON ("
134e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_name = settings.account_name AND "
135e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_type = settings.account_type) "
136e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN data ON (data.mimetype_id=? AND "
137e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "data.raw_contact_id = raw_contacts._id) "
138e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN groups ON (groups._id = data." + GroupMembership.GROUP_ROW_ID
139e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + ")";
140e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
141e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        // NOTE: This requires late binding of GroupMembership MIME-type
142e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS = "settings "
143e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN raw_contacts ON ("
144e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_name = settings.account_name AND "
145e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_type = settings.account_type) "
146e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN data ON (data.mimetype_id=? AND "
147e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "data.raw_contact_id = raw_contacts._id) "
148e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
149e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
150d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS = "data "
1511b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
1521b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) "
153d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
154ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
1555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_GROUPS = "data "
1561b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
1571b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) "
15867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                + "LEFT OUTER JOIN packages ON (data.package_id = packages._id) "
1599261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "LEFT OUTER JOIN groups "
1609261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "  ON (mimetypes.mimetype='" + GroupMembership.CONTENT_ITEM_TYPE + "' "
1619261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "      AND groups._id = data." + GroupMembership.GROUP_ROW_ID + ") ";
162ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
163ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String GROUPS_JOIN_PACKAGES = "groups "
164ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN packages ON (groups.package_id = packages._id)";
165ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
166b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
167b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String ACTIVITIES = "activities";
168b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
169ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String ACTIVITIES_JOIN_MIMETYPES = "activities "
170ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (activities.mimetype_id = mimetypes._id)";
171b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
172d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String ACTIVITIES_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS =
1735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                "activities "
17467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                + "LEFT OUTER JOIN packages ON (activities.package_id = packages._id) "
175ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (activities.mimetype_id = mimetypes._id) "
1765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "LEFT OUTER JOIN raw_contacts ON (activities.author_contact_id = " +
177fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        "raw_contacts._id) "
178d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
1797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana
1805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String NAME_LOOKUP_JOIN_RAW_CONTACTS = "name_lookup "
1815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "INNER JOIN raw_contacts ON (name_lookup.raw_contact_id = raw_contacts._id)";
182b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
183b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public interface Views {
1854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String DATA_ALL = "view_data";
1864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String DATA_RESTRICTED = "view_data_restricted";
1874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
1884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String RAW_CONTACTS_ALL = "view_raw_contacts";
1894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String RAW_CONTACTS_RESTRICTED = "view_raw_contacts_restricted";
1904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
1914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String CONTACTS_ALL = "view_contacts";
1924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String CONTACTS_RESTRICTED = "view_contacts_restricted";
19389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
194a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        public static final String ENTITIES = "view_entities";
195a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        public static final String ENTITIES_RESTRICTED = "view_entities_restricted";
196a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
197a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        public static final String RAW_ENTITIES = "view_raw_entities";
198a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        public static final String RAW_ENTITIES_RESTRICTED = "view_raw_entities_restricted";
199a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
20089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        public static final String GROUPS_ALL = "view_groups";
2014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
2024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
2031f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    public interface Clauses {
204e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String MIMETYPE_IS_GROUP_MEMBERSHIP = MimetypesColumns.CONCRETE_MIMETYPE + "='"
205e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + GroupMembership.CONTENT_ITEM_TYPE + "'";
206ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
207e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String BELONGS_TO_GROUP = DataColumns.CONCRETE_GROUP_ID + "="
208ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + GroupsColumns.CONCRETE_ID;
209ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
21068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey        final String HAVING_NO_GROUPS = "COUNT(" + DataColumns.CONCRETE_GROUP_ID + ") == 0";
2119261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana
21268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey        final String GROUP_BY_ACCOUNT_CONTACT_ID = SettingsColumns.CONCRETE_ACCOUNT_NAME + ","
21368936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey                + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "," + RawContacts.CONTACT_ID;
214e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
215e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String RAW_CONTACT_IS_LOCAL = RawContactsColumns.CONCRETE_ACCOUNT_NAME
216e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + " IS NULL AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL";
217e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
218e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String ZERO_GROUP_MEMBERSHIPS = "COUNT(" + GroupsColumns.CONCRETE_ID + ")=0";
219e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
2201a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey        final String OUTER_RAW_CONTACTS = "outer_raw_contacts";
2211a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey        final String OUTER_RAW_CONTACTS_ID = OUTER_RAW_CONTACTS + "." + RawContacts._ID;
2221a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey
223b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov        final String CONTACT_IS_VISIBLE =
224b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                "SELECT " +
2251a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey                    "MAX((SELECT (CASE WHEN " +
226b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                        "(CASE" +
227b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " WHEN " + RAW_CONTACT_IS_LOCAL +
228b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " THEN 1 " +
229b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " WHEN " + ZERO_GROUP_MEMBERSHIPS +
230b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " THEN " + Settings.UNGROUPED_VISIBLE +
231b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " ELSE MAX(" + Groups.GROUP_VISIBLE + ")" +
232b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                         "END)=1 THEN 1 ELSE 0 END)" +
233b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS_JOIN_SETTINGS_DATA_GROUPS +
2341a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey                " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + OUTER_RAW_CONTACTS_ID + "))" +
2351a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey                " FROM " + Tables.RAW_CONTACTS + " AS " + OUTER_RAW_CONTACTS +
236b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
237b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                " GROUP BY " + RawContacts.CONTACT_ID;
238e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
239e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String GROUP_HAS_ACCOUNT_AND_SOURCE_ID = Groups.SOURCE_ID + "=? AND "
240e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + Groups.ACCOUNT_NAME + "=? AND " + Groups.ACCOUNT_TYPE + "=?";
2414394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
2424394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        public static final String CONTACT_VISIBLE =
2434394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            "EXISTS (SELECT _id FROM " + Tables.VISIBLE_CONTACTS
2444394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                + " WHERE " + Tables.CONTACTS +"." + Contacts._ID
2454394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        + "=" + Tables.VISIBLE_CONTACTS +"." + Contacts._ID + ")";
2461f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    }
2471f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
248d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    public interface ContactsColumns {
2494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        /**
2504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov         * This flag is set for a contact if it has only one constituent raw contact and
2514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov         * it is restricted.
2524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov         */
25367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String SINGLE_IS_RESTRICTED = "single_is_restricted";
254ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
255a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        public static final String LAST_STATUS_UPDATE_ID = "status_update_id";
256a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov
257d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_ID = Tables.CONTACTS + "." + BaseColumns._ID;
25867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
259d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_TIMES_CONTACTED = Tables.CONTACTS + "."
260d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.TIMES_CONTACTED;
261d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_LAST_TIME_CONTACTED = Tables.CONTACTS + "."
262d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.LAST_TIME_CONTACTED;
263d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_STARRED = Tables.CONTACTS + "." + Contacts.STARRED;
264d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_CUSTOM_RINGTONE = Tables.CONTACTS + "."
265d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.CUSTOM_RINGTONE;
266d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_SEND_TO_VOICEMAIL = Tables.CONTACTS + "."
267d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.SEND_TO_VOICEMAIL;
2682d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill        public static final String CONCRETE_LOOKUP_KEY = Tables.CONTACTS + "."
2692d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill                + Contacts.LOOKUP_KEY;
270619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
271619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
2726cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov    public interface RawContactsColumns {
27333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_ID =
2745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + BaseColumns._ID;
2759261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana        public static final String CONCRETE_ACCOUNT_NAME =
2765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.ACCOUNT_NAME;
2779261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana        public static final String CONCRETE_ACCOUNT_TYPE =
2785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.ACCOUNT_TYPE;
27933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_SOURCE_ID =
2805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.SOURCE_ID;
28133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_VERSION =
2825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.VERSION;
28333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_DIRTY =
2845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.DIRTY;
28533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_DELETED =
2865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.DELETED;
2877a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC1 =
2887a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC1;
2897a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC2 =
2907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC2;
2917a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC3 =
2927a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC3;
2937a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC4 =
2947a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC4;
295c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey        public static final String CONCRETE_STARRED =
296c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey                Tables.RAW_CONTACTS + "." + RawContacts.STARRED;
297bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey        public static final String CONCRETE_IS_RESTRICTED =
298bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey                Tables.RAW_CONTACTS + "." + RawContacts.IS_RESTRICTED;
2998e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov
3005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        public static final String DISPLAY_NAME = RawContacts.DISPLAY_NAME_PRIMARY;
3015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        public static final String DISPLAY_NAME_SOURCE = RawContacts.DISPLAY_NAME_SOURCE;
3028e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov        public static final String AGGREGATION_NEEDED = "aggregation_needed";
303fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
304fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        public static final String CONCRETE_DISPLAY_NAME =
305fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Tables.RAW_CONTACTS + "." + DISPLAY_NAME;
306fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        public static final String CONCRETE_CONTACT_ID =
307fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.CONTACT_ID;
308f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        public static final String CONCRETE_NAME_VERIFIED =
309f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.NAME_VERIFIED;
310619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
311619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
312619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    public interface DataColumns {
31367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String PACKAGE_ID = "package_id";
314b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE_ID = "mimetype_id";
315ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
316ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.DATA + "." + BaseColumns._ID;
317226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_MIMETYPE_ID = Tables.DATA + "." + MIMETYPE_ID;
318d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_RAW_CONTACT_ID = Tables.DATA + "."
319d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Data.RAW_CONTACT_ID;
320ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_GROUP_ID = Tables.DATA + "."
321ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + GroupMembership.GROUP_ROW_ID;
322e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov
323e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA1 = Tables.DATA + "." + Data.DATA1;
324e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA2 = Tables.DATA + "." + Data.DATA2;
325e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA3 = Tables.DATA + "." + Data.DATA3;
326e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA4 = Tables.DATA + "." + Data.DATA4;
327e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA5 = Tables.DATA + "." + Data.DATA5;
328e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA6 = Tables.DATA + "." + Data.DATA6;
329e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA7 = Tables.DATA + "." + Data.DATA7;
330e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA8 = Tables.DATA + "." + Data.DATA8;
331e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA9 = Tables.DATA + "." + Data.DATA9;
332e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA10 = Tables.DATA + "." + Data.DATA10;
3330f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA11 = Tables.DATA + "." + Data.DATA11;
3340f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA12 = Tables.DATA + "." + Data.DATA12;
3350f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA13 = Tables.DATA + "." + Data.DATA13;
3360f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA14 = Tables.DATA + "." + Data.DATA14;
3370f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA15 = Tables.DATA + "." + Data.DATA15;
338e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_IS_PRIMARY = Tables.DATA + "." + Data.IS_PRIMARY;
339226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_PACKAGE_ID = Tables.DATA + "." + PACKAGE_ID;
340e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov    }
341e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov
3420f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    // Used only for legacy API support
3430f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    public interface ExtensionsColumns {
3440f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String NAME = Data.DATA1;
3450f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String VALUE = Data.DATA2;
3460f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    }
3470f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov
3480f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    public interface GroupMembershipColumns {
3495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = Data.RAW_CONTACT_ID;
3500f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String GROUP_ROW_ID = GroupMembership.GROUP_ROW_ID;
3510f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    }
3520f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov
353e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov    public interface PhoneColumns {
354e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String NORMALIZED_NUMBER = Data.DATA4;
355e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_NORMALIZED_NUMBER = DataColumns.CONCRETE_DATA4;
356ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
357ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
358ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface GroupsColumns {
35967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String PACKAGE_ID = "package_id";
36067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
361ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.GROUPS + "." + BaseColumns._ID;
36267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String CONCRETE_SOURCE_ID = Tables.GROUPS + "." + Groups.SOURCE_ID;
363341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey        public static final String CONCRETE_ACCOUNT_NAME = Tables.GROUPS + "." + Groups.ACCOUNT_NAME;
364341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey        public static final String CONCRETE_ACCOUNT_TYPE = Tables.GROUPS + "." + Groups.ACCOUNT_TYPE;
365341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey    }
366b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
367b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface ActivitiesColumns {
368b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PACKAGE_ID = "package_id";
369b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE_ID = "mimetype_id";
370b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
371b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
372b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface PhoneLookupColumns {
373b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
374b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA_ID = "data_id";
3755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = "raw_contact_id";
376b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String NORMALIZED_NUMBER = "normalized_number";
37736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        public static final String MIN_MATCH = "min_match";
378b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
379b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
380a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    public interface NameLookupColumns {
3815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = "raw_contact_id";
38214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        public static final String DATA_ID = "data_id";
383a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NORMALIZED_NAME = "normalized_name";
384a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NAME_TYPE = "name_type";
385a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
386a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
387a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov    public final static class NameLookupType {
3882a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NAME_EXACT = 0;
3892a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NAME_VARIANT = 1;
3902a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NAME_COLLATION_KEY = 2;
3912a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NICKNAME = 3;
3922a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int EMAIL_BASED_NICKNAME = 4;
393a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka        public static final int ORGANIZATION = 5;
3944cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao        public static final int NAME_SHORTHAND = 6;
395f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        public static final int NAME_CONSONANTS = 7;
396a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
397a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        // This is the highest name lookup type code plus one
3985086b63bf3de5f26f495b640e85259c0ebf5ca47Dmitri Plotnikov        public static final int TYPE_COUNT = 8;
399a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov
400a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        public static boolean isBasedOnStructuredName(int nameLookupType) {
4012a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov            return nameLookupType == NameLookupType.NAME_EXACT
4022a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov                    || nameLookupType == NameLookupType.NAME_VARIANT
4032a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov                    || nameLookupType == NameLookupType.NAME_COLLATION_KEY;
404a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        }
405a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
406a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
407ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface PackagesColumns {
408b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
409b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PACKAGE = "package";
410226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana
411226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_ID = Tables.PACKAGES + "." + _ID;
412b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
413b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
414ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface MimetypesColumns {
415b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
416b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE = "mimetype";
417ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
418ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.MIMETYPES + "." + BaseColumns._ID;
419ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_MIMETYPE = Tables.MIMETYPES + "." + MIMETYPE;
420b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
421b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
422b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov    public interface AggregationExceptionColumns {
423b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        public static final String _ID = BaseColumns._ID;
424b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov    }
425b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
426b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    public interface NicknameLookupColumns {
427b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String NAME = "name";
428b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String CLUSTER = "cluster";
429b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    }
430b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
431e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey    public interface SettingsColumns {
432e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String CONCRETE_ACCOUNT_NAME = Tables.SETTINGS + "."
433e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + Settings.ACCOUNT_NAME;
434e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String CONCRETE_ACCOUNT_TYPE = Tables.SETTINGS + "."
435e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + Settings.ACCOUNT_TYPE;
436e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey    }
437e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
4384dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov    public interface PresenceColumns {
4394dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov        String RAW_CONTACT_ID = "presence_raw_contact_id";
440bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        String CONTACT_ID = "presence_contact_id";
4414dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov    }
4424dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov
443e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov    public interface AggregatedPresenceColumns {
444e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        String CONTACT_ID = "presence_contact_id";
4453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4463296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_CONTACT_ID = Tables.AGGREGATED_PRESENCE + "." + CONTACT_ID;
447e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov    }
448e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov
449a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov    public interface StatusUpdatesColumns {
450a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        String DATA_ID = "status_update_data_id";
4513296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4523296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_DATA_ID = Tables.STATUS_UPDATES + "." + DATA_ID;
4533296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4543296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_PRESENCE = Tables.STATUS_UPDATES + "." + StatusUpdates.PRESENCE;
4553296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS = Tables.STATUS_UPDATES + "." + StatusUpdates.STATUS;
4563296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_TIMESTAMP = Tables.STATUS_UPDATES + "."
4573296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey                + StatusUpdates.STATUS_TIMESTAMP;
4583296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_RES_PACKAGE = Tables.STATUS_UPDATES + "."
4593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey                + StatusUpdates.STATUS_RES_PACKAGE;
4603296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_LABEL = Tables.STATUS_UPDATES + "." + StatusUpdates.STATUS_LABEL;
4613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_ICON = Tables.STATUS_UPDATES + "." + StatusUpdates.STATUS_ICON;
4623296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey    }
4633296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4643296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey    public interface ContactsStatusUpdatesColumns {
4653296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String ALIAS = "contacts_" + Tables.STATUS_UPDATES;
4663296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4673296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_DATA_ID = ALIAS + "." + StatusUpdatesColumns.DATA_ID;
4683296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4693296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_PRESENCE = ALIAS + "." + StatusUpdates.PRESENCE;
4703296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS = ALIAS + "." + StatusUpdates.STATUS;
4713296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_TIMESTAMP = ALIAS + "." + StatusUpdates.STATUS_TIMESTAMP;
4723296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_RES_PACKAGE = ALIAS + "." + StatusUpdates.STATUS_RES_PACKAGE;
4733296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_LABEL = ALIAS + "." + StatusUpdates.STATUS_LABEL;
4743296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_ICON = ALIAS + "." + StatusUpdates.STATUS_ICON;
475a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov    }
476a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov
477b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public interface PropertiesColumns {
478b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        String PROPERTY_KEY = "property_key";
479b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        String PROPERTY_VALUE = "property_value";
480b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
481b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
482e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    public static final class DirectoryColumns {
483e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov        public static final String TYPE_RESOURCE_NAME = "typeResourceName";
484e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    }
485e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov
4863296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey    /** In-memory cache of previously found MIME-type mappings */
487bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    private final HashMap<String, Long> mMimetypeCache = new HashMap<String, Long>();
488b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** In-memory cache of previously found package name mappings */
489bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    private final HashMap<String, Long> mPackageCache = new HashMap<String, Long>();
490b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
4912a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdEmail;
4922a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdIm;
4932a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdStructuredName;
4942a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdOrganization;
4952a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdNickname;
4962a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdPhone;
497b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
498b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** Compiled statements for querying and inserting mappings */
499b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mMimetypeQuery;
500b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mPackageQuery;
501d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    private SQLiteStatement mContactIdQuery;
502f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    private SQLiteStatement mAggregationModeQuery;
503b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mMimetypeInsert;
504b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mPackageInsert;
505b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mDataMimetypeQuery;
506b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mActivitiesMimetypeQuery;
507b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
50878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for setting a data record to the primary. */
50978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mSetPrimaryStatement;
51078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for setting a data record to the super primary. */
51178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mSetSuperPrimaryStatement;
51278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for clearing super primary of a single record. */
51378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mClearSuperPrimaryStatement;
51478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for updating a contact display name */
51578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mRawContactDisplayNameUpdate;
51678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
51778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mNameLookupInsert;
51878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mNameLookupDelete;
51978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateAutoTimestamp;
52078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateInsert;
52178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateReplace;
52278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusAttributionUpdate;
52378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateDelete;
52478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mResetNameVerifiedForOtherRawContacts;
52578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
526b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private final Context mContext;
5272a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private final boolean mDatabaseOptimizationEnabled;
52835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    private final SyncStateContentProviderHelper mSyncState;
529e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    private final CountryMonitor mCountryMonitor;
5305df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov    private StringBuilder mSb = new StringBuilder();
531f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov
532f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    private boolean mReopenDatabase = false;
533f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
534b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    private static ContactsDatabaseHelper sSingleton = null;
535b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
53636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    private boolean mUseStrictPhoneNumberComparison;
5373a6a49cfb06272e3e25f3c390a9cf4002da6e34dDaisuke Miyakawa
538d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    /**
539d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton     * List of package names with access to {@link RawContacts#IS_RESTRICTED} data.
540d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton     */
541d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    private String[] mUnrestrictedPackages;
542d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton
543b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    public static synchronized ContactsDatabaseHelper getInstance(Context context) {
544b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (sSingleton == null) {
5452a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            sSingleton = new ContactsDatabaseHelper(context, DATABASE_NAME, true);
546b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
547b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return sSingleton;
548b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
549b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
5501f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    /**
55131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov     * Private constructor, callers except unit tests should obtain an instance through
55235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana     * {@link #getInstance(android.content.Context)} instead.
5531f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey     */
554b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    ContactsDatabaseHelper(Context context) {
5552a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        this(context, null, false);
5562a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
5572a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
5582a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private ContactsDatabaseHelper(
5592a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            Context context, String databaseName, boolean optimizationEnabled) {
5602a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        super(context, databaseName, null, DATABASE_VERSION);
5612a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mDatabaseOptimizationEnabled = optimizationEnabled;
562d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        Resources resources = context.getResources();
563619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
564b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        mContext = context;
56528b3769e3fcecae56c3fc70cbcb0f95282b9640eFred Quintana        mSyncState = new SyncStateContentProviderHelper();
566e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        mCountryMonitor = new CountryMonitor(context);
56736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        mUseStrictPhoneNumberComparison =
568d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                resources.getBoolean(
569d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                        com.android.internal.R.bool.config_use_strict_phone_number_comparation);
5700f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        int resourceId = resources.getIdentifier("unrestricted_packages", "array",
5710f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov                context.getPackageName());
5720f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        if (resourceId != 0) {
5730f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov            mUnrestrictedPackages = resources.getStringArray(resourceId);
5740f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        } else {
5750f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov            mUnrestrictedPackages = new String[0];
5760f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        }
577b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
578b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
5792a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private void refreshDatabaseCaches(SQLiteDatabase db) {
58078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateDelete = null;
58178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace = null;
58278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateInsert = null;
58378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateAutoTimestamp = null;
58478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusAttributionUpdate = null;
58578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts = null;
58678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate = null;
58778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement = null;
58878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement = null;
58978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement = null;
59078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert = null;
59178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupDelete = null;
59278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mPackageQuery = null;
59378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mPackageInsert = null;
59478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mDataMimetypeQuery = null;
59578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mActivitiesMimetypeQuery = null;
59678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mContactIdQuery = null;
59778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mAggregationModeQuery = null;
5982a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
5992a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimetypeCache.clear();
6002a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mPackageCache.clear();
6012a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
6022a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimetypeQuery = db.compileStatement(
6032a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                "SELECT " + MimetypesColumns._ID +
6042a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                " FROM " + Tables.MIMETYPES +
6052a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                " WHERE " + MimetypesColumns.MIMETYPE + "=?");
6062a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
6072a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimetypeInsert = db.compileStatement(
6082a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                "INSERT INTO " + Tables.MIMETYPES + "("
6092a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                        + MimetypesColumns.MIMETYPE +
6102a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                ") VALUES (?)");
6112a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
6122a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdEmail = getMimeTypeId(Email.CONTENT_ITEM_TYPE);
6132a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdIm = getMimeTypeId(Im.CONTENT_ITEM_TYPE);
6142a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdStructuredName = getMimeTypeId(StructuredName.CONTENT_ITEM_TYPE);
6152a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdOrganization = getMimeTypeId(Organization.CONTENT_ITEM_TYPE);
6162a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdNickname = getMimeTypeId(Nickname.CONTENT_ITEM_TYPE);
6172a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdPhone = getMimeTypeId(Phone.CONTENT_ITEM_TYPE);
61878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
61978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
620b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
621b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onOpen(SQLiteDatabase db) {
6222a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        refreshDatabaseCaches(db);
62335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
62478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSyncState.onDatabaseOpened(db);
6251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
6261f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        db.execSQL("ATTACH DATABASE ':memory:' AS " + DATABASE_PRESENCE + ";");
627e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS " + DATABASE_PRESENCE + "." + Tables.PRESENCE + " ("+
62882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.DATA_ID + " INTEGER PRIMARY KEY REFERENCES data(_id)," +
62982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.PROTOCOL + " INTEGER NOT NULL," +
63082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.CUSTOM_PROTOCOL + " TEXT," +
63182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.IM_HANDLE + " TEXT," +
63282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.IM_ACCOUNT + " TEXT," +
633a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                PresenceColumns.CONTACT_ID + " INTEGER REFERENCES contacts(_id)," +
634a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                PresenceColumns.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
63582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.PRESENCE + " INTEGER," +
636aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                StatusUpdates.CHAT_CAPABILITY + " INTEGER NOT NULL DEFAULT 0," +
63782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                "UNIQUE(" + StatusUpdates.PROTOCOL + ", " + StatusUpdates.CUSTOM_PROTOCOL
63882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                    + ", " + StatusUpdates.IM_HANDLE + ", " + StatusUpdates.IM_ACCOUNT + ")" +
6391f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        ");");
6401f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
641e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE INDEX IF NOT EXISTS " + DATABASE_PRESENCE + ".presenceIndex" + " ON "
6424dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov                + Tables.PRESENCE + " (" + PresenceColumns.RAW_CONTACT_ID + ");");
64309562b6c3a420ded0d02b9bd2290de2dbab9e304Vasu Nori        db.execSQL("CREATE INDEX IF NOT EXISTS " + DATABASE_PRESENCE + ".presenceIndex2" + " ON "
64409562b6c3a420ded0d02b9bd2290de2dbab9e304Vasu Nori                + Tables.PRESENCE + " (" + PresenceColumns.CONTACT_ID + ");");
645e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov
646e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS "
647aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + DATABASE_PRESENCE + "." + Tables.AGGREGATED_PRESENCE + " ("+
648e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov                AggregatedPresenceColumns.CONTACT_ID
649e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov                        + " INTEGER PRIMARY KEY REFERENCES contacts(_id)," +
650632248ae0053fa99b1f5b4cfaab3e55b7453fcb1Vasu Nori                StatusUpdates.PRESENCE + " INTEGER," +
651aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                StatusUpdates.CHAT_CAPABILITY + " INTEGER NOT NULL DEFAULT 0" +
652e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        ");");
653bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
654bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
655bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_deleted"
656bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEFORE DELETE ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
657bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
658bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + "   DELETE FROM " + Tables.AGGREGATED_PRESENCE
659bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + "     WHERE " + AggregatedPresenceColumns.CONTACT_ID + " = " +
660bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        "(SELECT " + PresenceColumns.CONTACT_ID +
661bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " FROM " + Tables.PRESENCE +
662bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " WHERE " + PresenceColumns.RAW_CONTACT_ID
663bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                + "=OLD." + PresenceColumns.RAW_CONTACT_ID +
664bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " AND NOT EXISTS" +
665bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                "(SELECT " + PresenceColumns.RAW_CONTACT_ID +
666bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " FROM " + Tables.PRESENCE +
667bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " WHERE " + PresenceColumns.CONTACT_ID
668bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                        + "=OLD." + PresenceColumns.CONTACT_ID +
669bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " AND " + PresenceColumns.RAW_CONTACT_ID
670bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                        + "!=OLD." + PresenceColumns.RAW_CONTACT_ID + "));"
671bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
672bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
673aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori        final String replaceAggregatePresenceSql =
674aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                "INSERT OR REPLACE INTO " + Tables.AGGREGATED_PRESENCE + "("
675093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + AggregatedPresenceColumns.CONTACT_ID + ", "
676093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.PRESENCE + ", "
677093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.CHAT_CAPABILITY + ")"
678093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                + " SELECT "
679093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + PresenceColumns.CONTACT_ID + ","
680093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.PRESENCE + ","
681093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.CHAT_CAPABILITY
682aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " FROM " + Tables.PRESENCE
683aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " WHERE "
684093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + " (ifnull(" + StatusUpdates.PRESENCE + ",0)  * 10 "
685093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                            + "+ ifnull(" + StatusUpdates.CHAT_CAPABILITY + ", 0))"
686093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + " = (SELECT "
687093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + "MAX (ifnull(" + StatusUpdates.PRESENCE + ",0)  * 10 "
688093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                                + "+ ifnull(" + StatusUpdates.CHAT_CAPABILITY + ", 0))"
689093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + " FROM " + Tables.PRESENCE
690093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + " WHERE " + PresenceColumns.CONTACT_ID
691093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                            + "=NEW." + PresenceColumns.CONTACT_ID
692093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + ")"
693093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                + " AND " + PresenceColumns.CONTACT_ID + "=NEW." + PresenceColumns.CONTACT_ID + ";";
694bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
695bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_inserted"
696bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " AFTER INSERT ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
697bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
698bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + replaceAggregatePresenceSql
699bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
700bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
701bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_updated"
702bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " AFTER UPDATE ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
703bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
704bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + replaceAggregatePresenceSql
705bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
706b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
707b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
708b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
709b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onCreate(SQLiteDatabase db) {
710b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        Log.i(TAG, "Bootstrapping database");
711b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
71235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        mSyncState.createDatabase(db);
71335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
714b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // One row per group of contacts corresponding to the same person
715d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.CONTACTS + " (" +
716b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
717fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
718d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.PHOTO_ID + " INTEGER REFERENCES data(_id)," +
719d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.CUSTOM_RINGTONE + " TEXT," +
720d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," +
721d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," +
722d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.LAST_TIME_CONTACTED + " INTEGER," +
723d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.STARRED + " INTEGER NOT NULL DEFAULT 0," +
724f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov                Contacts.HAS_PHONE_NUMBER + " INTEGER NOT NULL DEFAULT 0," +
7255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                Contacts.LOOKUP_KEY + " TEXT," +
726a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                ContactsColumns.LAST_STATUS_UPDATE_ID + " INTEGER REFERENCES data(_id)," +
7274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.SINGLE_IS_RESTRICTED + " INTEGER NOT NULL DEFAULT 0" +
728b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
729b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
73054d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX contacts_has_phone_index ON " + Tables.CONTACTS + " (" +
73154d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                Contacts.HAS_PHONE_NUMBER +
73254d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
73354d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
73454d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX contacts_restricted_index ON " + Tables.CONTACTS + " (" +
73554d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                ContactsColumns.SINGLE_IS_RESTRICTED +
73654d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
73754d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
738fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_name_raw_contact_id_index ON " + Tables.CONTACTS + " (" +
739fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID +
740fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
741fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
742b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Contacts table
7435ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.RAW_CONTACTS + " (" +
7446cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
7456cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.IS_RESTRICTED + " INTEGER DEFAULT 0," +
7466cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.ACCOUNT_NAME + " STRING DEFAULT NULL, " +
7476cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + " STRING DEFAULT NULL, " +
7486cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.SOURCE_ID + " TEXT," +
74997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                RawContacts.RAW_CONTACT_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
7506cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.VERSION + " INTEGER NOT NULL DEFAULT 1," +
75173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov                RawContacts.DIRTY + " INTEGER NOT NULL DEFAULT 0," +
75233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov                RawContacts.DELETED + " INTEGER NOT NULL DEFAULT 0," +
75354d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                RawContacts.CONTACT_ID + " INTEGER REFERENCES contacts(_id)," +
7546cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.AGGREGATION_MODE + " INTEGER NOT NULL DEFAULT " +
7556cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                        RawContacts.AGGREGATION_MODE_DEFAULT + "," +
7568e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov                RawContactsColumns.AGGREGATION_NEEDED + " INTEGER NOT NULL DEFAULT 1," +
7576cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.CUSTOM_RINGTONE + " TEXT," +
7586cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," +
7596cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," +
7606cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.LAST_TIME_CONTACTED + " INTEGER," +
76133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov                RawContacts.STARRED + " INTEGER NOT NULL DEFAULT 0," +
7625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_PRIMARY + " TEXT," +
7635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_ALTERNATIVE + " TEXT," +
7645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_SOURCE + " INTEGER NOT NULL DEFAULT " +
76525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov                        DisplayNameSources.UNDEFINED + "," +
7665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.PHONETIC_NAME + " TEXT," +
7675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.PHONETIC_NAME_STYLE + " TEXT," +
768de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                RawContacts.SORT_KEY_PRIMARY + " TEXT COLLATE " +
769de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                        ContactsProvider2.PHONEBOOK_COLLATOR_NAME + "," +
770de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                RawContacts.SORT_KEY_ALTERNATIVE + " TEXT COLLATE " +
771de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                        ContactsProvider2.PHONEBOOK_COLLATOR_NAME + "," +
772f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                RawContacts.NAME_VERIFIED + " INTEGER NOT NULL DEFAULT 0," +
7733cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC1 + " TEXT, " +
7743cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC2 + " TEXT, " +
7753cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC3 + " TEXT, " +
7763cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC4 + " TEXT " +
777b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
778b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
77954d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contacts_contact_id_index ON " + Tables.RAW_CONTACTS + " (" +
78054d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                RawContacts.CONTACT_ID +
78154d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
78254d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
7835f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contacts_source_id_index ON " + Tables.RAW_CONTACTS + " (" +
7845f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.SOURCE_ID + ", " +
7855f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + ", " +
7865f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.ACCOUNT_NAME +
7875f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        ");");
7885f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov
789f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        // TODO readd the index and investigate a controlled use of it
790f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//        db.execSQL("CREATE INDEX raw_contacts_agg_index ON " + Tables.RAW_CONTACTS + " (" +
791f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//                RawContactsColumns.AGGREGATION_NEEDED +
792f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//        ");");
7938e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov
794b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Package name mapping table
795ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PACKAGES + " (" +
796ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                PackagesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
797ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                PackagesColumns.PACKAGE + " TEXT NOT NULL" +
798b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
799b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
800ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // Mimetype mapping table
801ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.MIMETYPES + " (" +
802ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                MimetypesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
803ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                MimetypesColumns.MIMETYPE + " TEXT NOT NULL" +
804b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
805b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
80608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        // Mimetype table requires an index on mime type
80708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX mime_type ON " + Tables.MIMETYPES + " (" +
80808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov                MimetypesColumns.MIMETYPE +
80908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        ");");
81008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
811b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Public generic data table
812b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.DATA + " (" +
813b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
81467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                DataColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
815b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                DataColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
81611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                Data.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
81797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                Data.IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
818f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.IS_PRIMARY + " INTEGER NOT NULL DEFAULT 0," +
819f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.IS_SUPER_PRIMARY + " INTEGER NOT NULL DEFAULT 0," +
820f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA_VERSION + " INTEGER NOT NULL DEFAULT 0," +
821f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA1 + " TEXT," +
822f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA2 + " TEXT," +
823f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA3 + " TEXT," +
824f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA4 + " TEXT," +
825f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA5 + " TEXT," +
826f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA6 + " TEXT," +
827f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA7 + " TEXT," +
828f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA8 + " TEXT," +
829f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA9 + " TEXT," +
83067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA10 + " TEXT," +
83167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA11 + " TEXT," +
83267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA12 + " TEXT," +
83367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA13 + " TEXT," +
83467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA14 + " TEXT," +
8353cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.DATA15 + " TEXT," +
8363cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC1 + " TEXT, " +
8373cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC2 + " TEXT, " +
8383cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC3 + " TEXT, " +
8393cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC4 + " TEXT " +
840b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
841b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
84211944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        db.execSQL("CREATE INDEX data_raw_contact_id ON " + Tables.DATA + " (" +
84311944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                Data.RAW_CONTACT_ID +
84411944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        ");");
84511944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
84611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        /**
84711944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov         * For email lookup and similar queries.
84811944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov         */
849f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov        db.execSQL("CREATE INDEX data_mimetype_data1_index ON " + Tables.DATA + " (" +
85011944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "," +
851f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov                Data.DATA1 +
85211944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        ");");
85311944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
854b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Private phone numbers table used for lookup
855b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" +
856f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.DATA_ID
857892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        + " INTEGER REFERENCES data(_id) NOT NULL," +
8585ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID
8595ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
86036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL," +
86136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL" +
862b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
863b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
864b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" +
865f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + "," +
866f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
867b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.DATA_ID +
868b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
869b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
87036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
87136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
87236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
87336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
87436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        ");");
87536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
876a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        // Private name/nickname table used for lookup
877a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.NAME_LOOKUP + " (" +
87814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                NameLookupColumns.DATA_ID
87914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                        + " INTEGER REFERENCES data(_id) NOT NULL," +
8805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID
8815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
88211944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                NameLookupColumns.NORMALIZED_NAME + " TEXT NOT NULL," +
88311944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                NameLookupColumns.NAME_TYPE + " INTEGER NOT NULL," +
88414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                "PRIMARY KEY ("
88514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                        + NameLookupColumns.DATA_ID + ", "
88611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                        + NameLookupColumns.NORMALIZED_NAME + ", "
88711944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                        + NameLookupColumns.NAME_TYPE + ")" +
888a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        ");");
889a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
89014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        db.execSQL("CREATE INDEX name_lookup_raw_contact_id_index ON " + Tables.NAME_LOOKUP + " (" +
89114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID +
89214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        ");");
89314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov
894b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.NICKNAME_LOOKUP + " (" +
895b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + " TEXT," +
896b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.CLUSTER + " TEXT" +
897b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        ");");
898b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
899b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX nickname_lookup_index ON " + Tables.NICKNAME_LOOKUP + " (" +
900b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + ", " +
901b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.CLUSTER +
902b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        ");");
903b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
904ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // Groups table
905ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.GROUPS + " (" +
906ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
90767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                GroupsColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
908035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana                Groups.ACCOUNT_NAME + " STRING DEFAULT NULL, " +
909035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana                Groups.ACCOUNT_TYPE + " STRING DEFAULT NULL, " +
910ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups.SOURCE_ID + " TEXT," +
9119261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                Groups.VERSION + " INTEGER NOT NULL DEFAULT 1," +
91273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov                Groups.DIRTY + " INTEGER NOT NULL DEFAULT 0," +
913ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups.TITLE + " TEXT," +
91467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Groups.TITLE_RES + " INTEGER," +
9150f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov                Groups.NOTES + " TEXT," +
9160f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov                Groups.SYSTEM_ID + " TEXT," +
91794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana                Groups.DELETED + " INTEGER NOT NULL DEFAULT 0," +
918eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Groups.GROUP_VISIBLE + " INTEGER NOT NULL DEFAULT 0," +
919ea547d55f864133861b2db44221ae0c2ac6c1a68Fred Quintana                Groups.SHOULD_SYNC + " INTEGER NOT NULL DEFAULT 1," +
920dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                Groups.AUTO_ADD + " INTEGER NOT NULL DEFAULT 0," +
921dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                Groups.FAVORITES + " INTEGER NOT NULL DEFAULT 0," +
922c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                Groups.GROUP_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
9233cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC1 + " TEXT, " +
9243cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC2 + " TEXT, " +
9253cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC3 + " TEXT, " +
9263cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC4 + " TEXT " +
927ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        ");");
928ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
9295f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        db.execSQL("CREATE INDEX groups_source_id_index ON " + Tables.GROUPS + " (" +
9305f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.SOURCE_ID + ", " +
9315f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.ACCOUNT_TYPE + ", " +
9325f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.ACCOUNT_NAME +
9335f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        ");");
9345f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov
935b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.AGGREGATION_EXCEPTIONS + " (" +
936b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                AggregationExceptionColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
937b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                AggregationExceptions.TYPE + " INTEGER NOT NULL, " +
9380c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1
9395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id), " +
9400c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2
9415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id)" +
942b0160a0bcf6d59eaa43fd501e124b95f873e0157Marc Blank        ");");
943b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
944b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index1 ON " +
945b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                Tables.AGGREGATION_EXCEPTIONS + " (" +
9460c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1 + ", " +
9470c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2 +
948b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        ");");
949b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
950b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index2 ON " +
951b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                Tables.AGGREGATION_EXCEPTIONS + " (" +
9520c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2 + ", " +
9530c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1 +
954b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        ");");
955b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
956eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.SETTINGS + " (" +
957eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.ACCOUNT_NAME + " STRING NOT NULL," +
958eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.ACCOUNT_TYPE + " STRING NOT NULL," +
959eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.UNGROUPED_VISIBLE + " INTEGER NOT NULL DEFAULT 0," +
960eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.SHOULD_SYNC + " INTEGER NOT NULL DEFAULT 1, " +
961eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                "PRIMARY KEY (" + Settings.ACCOUNT_NAME + ", " +
962e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    Settings.ACCOUNT_TYPE + ") ON CONFLICT REPLACE" +
963eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        ");");
964eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey
9654394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.VISIBLE_CONTACTS + " (" +
9664394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
9674394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
9684394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
969385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DEFAULT_DIRECTORY + " (" +
970385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
971385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        ");");
972385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
973e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        // The table for recent calls is here so we can do table joins
974e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        // on people, phones, and calls all in one place.
975e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.CALLS + " (" +
976e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
977e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.NUMBER + " TEXT," +
978e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.DATE + " INTEGER," +
979e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.DURATION + " INTEGER," +
980e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.TYPE + " INTEGER," +
981e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.NEW + " INTEGER," +
982e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NAME + " TEXT," +
983e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NUMBER_TYPE + " INTEGER," +
9842530512f639c4979fd7371c7dd25dd67e8118124Bai Tao                Calls.CACHED_NUMBER_LABEL + " TEXT," +
9852530512f639c4979fd7371c7dd25dd67e8118124Bai Tao                Calls.COUNTRY_ISO + " TEXT" + ");");
986e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov
987b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Activities table
988b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.ACTIVITIES + " (" +
989b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
99067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                ActivitiesColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
991b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                ActivitiesColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
992b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.RAW_ID + " TEXT," +
993499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.IN_REPLY_TO + " TEXT," +
9945ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Activities.AUTHOR_CONTACT_ID +  " INTEGER REFERENCES raw_contacts(_id)," +
9955ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Activities.TARGET_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
996b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.PUBLISHED + " INTEGER NOT NULL," +
997499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.THREAD_PUBLISHED + " INTEGER NOT NULL," +
998b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.TITLE + " TEXT NOT NULL," +
999b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.SUMMARY + " TEXT," +
1000adb55c2d8295d300961d86a3605c8ddc469cd4a2Dmitri Plotnikov                Activities.LINK + " TEXT, " +
1001b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.THUMBNAIL + " BLOB" +
1002b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
1003b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1004a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.STATUS_UPDATES + " (" +
1005a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                StatusUpdatesColumns.DATA_ID + " INTEGER PRIMARY KEY REFERENCES data(_id)," +
10060a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS + " TEXT," +
10070a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_TIMESTAMP + " INTEGER," +
10080a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_RES_PACKAGE + " TEXT, " +
10090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_LABEL + " INTEGER, " +
10100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_ICON + " INTEGER" +
1011a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        ");");
1012a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov
1013b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.PROPERTIES + " (" +
1014b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_KEY + " TEXT PRIMARY KEY, " +
1015b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_VALUE + " TEXT " +
1016b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ");");
1017b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
1018743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.ACCOUNTS + " (" +
1019743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov                RawContacts.ACCOUNT_NAME + " TEXT, " +
1020743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + " TEXT " +
1021743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        ");");
1022743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
1023743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // Allow contacts without any account to be created for now.  Achieve that
1024743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // by inserting a fake account with both type and name as NULL.
1025743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // This "account" should be eliminated as soon as the first real writable account
1026743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // is added to the phone.
1027743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        db.execSQL("INSERT INTO accounts VALUES(NULL, NULL)");
1028743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
1029d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        createDirectoriesTable(db);
1030d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
1031a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        createContactsViews(db);
1032a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        createGroupsView(db);
1033fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        createContactsTriggers(db);
1034916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        createContactsIndexes(db);
10354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
1036a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        loadNicknameLookupTable(db);
1037a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1038a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        // Add the legacy API support views, etc
1039a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        LegacyApiSupport.createDatabase(db);
1040a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
10412a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        if (mDatabaseOptimizationEnabled) {
10422a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // This will create a sqlite_stat1 table that is used for query optimization
10432a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            db.execSQL("ANALYZE;");
1044a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
10452a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            updateSqliteStats(db);
1046a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
10472a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // We need to close and reopen the database connection so that the stats are
10482a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // taken into account. Make a note of it and do the actual reopening in the
10492a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // getWritableDatabase method.
10502a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            mReopenDatabase = true;
10512a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        }
1052a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1053a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        ContentResolver.requestSync(null /* all accounts */,
1054a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                ContactsContract.AUTHORITY, new Bundle());
1055a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    }
1056a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1057d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    private void createDirectoriesTable(SQLiteDatabase db) {
1058d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DIRECTORIES + "(" +
1059d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
1060d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.PACKAGE_NAME + " TEXT NOT NULL," +
1061d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.DIRECTORY_AUTHORITY + " TEXT NOT NULL," +
1062d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.TYPE_RESOURCE_ID + " INTEGER," +
1063e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov                DirectoryColumns.TYPE_RESOURCE_NAME + " TEXT," +
1064d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.ACCOUNT_TYPE + " TEXT," +
1065d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.ACCOUNT_NAME + " TEXT," +
1066d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.DISPLAY_NAME + " TEXT, " +
1067d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.EXPORT_SUPPORT + " INTEGER NOT NULL" +
106897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                        " DEFAULT " + Directory.EXPORT_SUPPORT_NONE + "," +
106997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                Directory.SHORTCUT_SUPPORT + " INTEGER NOT NULL" +
10703d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        " DEFAULT " + Directory.SHORTCUT_SUPPORT_NONE + "," +
10713d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                Directory.PHOTO_SUPPORT + " INTEGER NOT NULL" +
10723d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        " DEFAULT " + Directory.PHOTO_SUPPORT_NONE +
1073d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        ");");
1074d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
10753d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        // Trigger a full scan of directories in the system
10763d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        setProperty(db, ContactDirectoryManager.PROPERTY_DIRECTORY_SCAN_COMPLETE, "0");
1077d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    }
1078d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
1079916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    private static void createContactsTriggers(SQLiteDatabase db) {
1080fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1081fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        /*
1082fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * Automatically delete Data rows when a raw contact is deleted.
1083fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         */
1084fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.RAW_CONTACTS + "_deleted;");
1085fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_deleted "
1086fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   BEFORE DELETE ON " + Tables.RAW_CONTACTS
1087fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1088fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.DATA
1089fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Data.RAW_CONTACT_ID
1090fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID + ";"
1091fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.AGGREGATION_EXCEPTIONS
1092fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + AggregationExceptions.RAW_CONTACT_ID1
1093fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID
1094fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "        OR " + AggregationExceptions.RAW_CONTACT_ID2
1095fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID + ";"
109635da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "   DELETE FROM " + Tables.VISIBLE_CONTACTS
109735da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
109835da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
109935da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
110035da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "           )=1;"
1101385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "   DELETE FROM " + Tables.DEFAULT_DIRECTORY
1102385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
1103385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
1104385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
1105385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "           )=1;"
1106fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.CONTACTS
1107fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
1108fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
1109fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
1110fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "           )=1;"
1111fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1112fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1113fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1114fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS contacts_times_contacted;");
11156c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        db.execSQL("DROP TRIGGER IF EXISTS raw_contacts_times_contacted;");
1116fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1117fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        /*
1118fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * Triggers that update {@link RawContacts#VERSION} when the contact is
1119fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * marked for deletion or any time a data row is inserted, updated or
1120fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * deleted.
1121fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         */
1122fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.RAW_CONTACTS + "_marked_deleted;");
1123fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_marked_deleted "
11247f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori                + "   AFTER UPDATE ON " + Tables.RAW_CONTACTS
1125fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1126fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1127fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET "
1128fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                +         RawContacts.VERSION + "=OLD." + RawContacts.VERSION + "+1 "
1129fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + RawContacts._ID
1130fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "       AND NEW." + RawContacts.DELETED + "!= OLD." + RawContacts.DELETED + ";"
1131fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1132fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1133fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.DATA + "_updated;");
11347f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_updated AFTER UPDATE ON " + Tables.DATA
1135fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1136fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.DATA
1137fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + Data.DATA_VERSION + "=OLD." + Data.DATA_VERSION + "+1 "
1138fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Data._ID + "=OLD." + Data._ID + ";"
1139fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1140fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + RawContacts.VERSION + "=" + RawContacts.VERSION + "+1 "
1141fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + Data.RAW_CONTACT_ID + ";"
1142fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1143fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1144fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.DATA + "_deleted;");
1145fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_deleted BEFORE DELETE ON " + Tables.DATA
1146fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1147fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1148fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + RawContacts.VERSION + "=" + RawContacts.VERSION + "+1 "
1149fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + Data.RAW_CONTACT_ID + ";"
1150fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.PHONE_LOOKUP
1151fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + PhoneLookupColumns.DATA_ID + "=OLD." + Data._ID + ";"
1152fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.STATUS_UPDATES
1153fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + StatusUpdatesColumns.DATA_ID + "=OLD." + Data._ID + ";"
1154fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.NAME_LOOKUP
1155fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + NameLookupColumns.DATA_ID + "=OLD." + Data._ID + ";"
1156fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1157fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1158fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1159fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.GROUPS + "_updated1;");
1160fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.GROUPS + "_updated1 "
11617f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori                + "   AFTER UPDATE ON " + Tables.GROUPS
1162fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1163fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.GROUPS
1164fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET "
1165fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                +         Groups.VERSION + "=OLD." + Groups.VERSION + "+1"
1166fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Groups._ID + "=OLD." + Groups._ID + ";"
1167fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1168fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov    }
1169fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1170916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    private static void createContactsIndexes(SQLiteDatabase db) {
1171916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
1172916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        db.execSQL("CREATE INDEX name_lookup_index ON " + Tables.NAME_LOOKUP + " (" +
1173916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.NORMALIZED_NAME + "," +
1174916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.NAME_TYPE + ", " +
1175916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID + ", " +
1176916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.DATA_ID +
1177916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        ");");
117804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
117904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS raw_contact_sort_key1_index");
118004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
118104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                RawContacts.SORT_KEY_PRIMARY +
118204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        ");");
118304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
118404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS raw_contact_sort_key2_index");
118504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key2_index ON " + Tables.RAW_CONTACTS + " (" +
118604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                RawContacts.SORT_KEY_ALTERNATIVE +
118704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        ");");
1188916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    }
1189916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov
1190a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    private static void createContactsViews(SQLiteDatabase db) {
1191a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.CONTACTS_ALL + ";");
1192a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.CONTACTS_RESTRICTED + ";");
1193a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.DATA_ALL + ";");
1194a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.DATA_RESTRICTED + ";");
1195a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_CONTACTS_ALL + ";");
1196a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_CONTACTS_RESTRICTED + ";");
1197a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_ENTITIES + ";");
1198a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_ENTITIES_RESTRICTED + ";");
1199a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.ENTITIES + ";");
1200a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.ENTITIES_RESTRICTED + ";");
1201a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
12024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String dataColumns =
12034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                Data.IS_PRIMARY + ", "
12044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.IS_SUPER_PRIMARY + ", "
12054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA_VERSION + ", "
12064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + PackagesColumns.PACKAGE + " AS " + Data.RES_PACKAGE + ","
12074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + MimetypesColumns.MIMETYPE + " AS " + Data.MIMETYPE + ", "
120897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + Data.IS_READ_ONLY + ", "
12094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA1 + ", "
12104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA2 + ", "
12114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA3 + ", "
12124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA4 + ", "
12134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA5 + ", "
12144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA6 + ", "
12154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA7 + ", "
12164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA8 + ", "
12174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA9 + ", "
12184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA10 + ", "
12194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA11 + ", "
12204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA12 + ", "
12214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA13 + ", "
12224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA14 + ", "
12234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA15 + ", "
12244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC1 + ", "
12254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC2 + ", "
12264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC3 + ", "
12274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC4;
12284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String syncColumns =
12304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AS " + RawContacts.ACCOUNT_NAME + ","
12314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AS " + RawContacts.ACCOUNT_TYPE + ","
12324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SOURCE_ID + " AS " + RawContacts.SOURCE_ID + ","
1233f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                + RawContactsColumns.CONCRETE_NAME_VERIFIED + " AS " + RawContacts.NAME_VERIFIED + ","
12344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_VERSION + " AS " + RawContacts.VERSION + ","
12354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DIRTY + " AS " + RawContacts.DIRTY + ","
12364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC1 + " AS " + RawContacts.SYNC1 + ","
12374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC2 + " AS " + RawContacts.SYNC2 + ","
12384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC3 + " AS " + RawContacts.SYNC3 + ","
12394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC4 + " AS " + RawContacts.SYNC4;
12404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12413d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        String baseContactColumns =
12423d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                Contacts.HAS_PHONE_NUMBER + ", "
12433d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.NAME_RAW_CONTACT_ID + ", "
12443d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.LOOKUP_KEY + ", "
12453d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.PHOTO_ID + ", "
12463d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Clauses.CONTACT_VISIBLE + " AS " + Contacts.IN_VISIBLE_GROUP + ", "
12473d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + ContactsColumns.LAST_STATUS_UPDATE_ID;
12483d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
12494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactOptionColumns =
12504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.CONCRETE_CUSTOM_RINGTONE
12514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.CUSTOM_RINGTONE + ","
12524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL
12534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.SEND_TO_VOICEMAIL + ","
12544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_LAST_TIME_CONTACTED
12554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.LAST_TIME_CONTACTED + ","
12564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_TIMES_CONTACTED
12574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.TIMES_CONTACTED + ","
12584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_STARRED
12594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.STARRED;
12604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String contactNameColumns =
12625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "name_raw_contact." + RawContacts.DISPLAY_NAME_SOURCE
12635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_SOURCE + ", "
12645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.DISPLAY_NAME_PRIMARY
12655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_PRIMARY + ", "
12665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.DISPLAY_NAME_ALTERNATIVE
12675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_ALTERNATIVE + ", "
12685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.PHONETIC_NAME
12695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.PHONETIC_NAME + ", "
12705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.PHONETIC_NAME_STYLE
12715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.PHONETIC_NAME_STYLE + ", "
12725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.SORT_KEY_PRIMARY
12735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.SORT_KEY_PRIMARY + ", "
12745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.SORT_KEY_ALTERNATIVE
12754394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        + " AS " + Contacts.SORT_KEY_ALTERNATIVE;
12765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
12774a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String dataSelect = "SELECT "
12784a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + Data._ID + ","
12794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.RAW_CONTACT_ID + ", "
1280fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + RawContacts.CONTACT_ID + ", "
12814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + syncColumns + ", "
12824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + dataColumns + ", "
12834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + contactOptionColumns + ", "
12845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + contactNameColumns + ", "
12853d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + baseContactColumns + ", "
12863d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
12873d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_URI) + ", "
12883d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
12893d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_THUMBNAIL_URI) + ", "
12904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
12914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.DATA
1292a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.MIMETYPES + " ON ("
12934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1294a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " ON ("
12954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1296a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.CONTACTS + " ON ("
1297fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   RawContactsColumns.CONCRETE_CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID + ")"
1298fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1299fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")"
1300a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1301a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
13024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
13034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1304f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1305a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                        + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
13064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.DATA_ALL + " AS " + dataSelect);
13084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.DATA_RESTRICTED + " AS " + dataSelect + " WHERE "
1309fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0");
13104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String rawContactOptionColumns =
13124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                RawContacts.CUSTOM_RINGTONE + ","
13134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.SEND_TO_VOICEMAIL + ","
13144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.LAST_TIME_CONTACTED + ","
13154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.TIMES_CONTACTED + ","
13164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.STARRED;
13174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String rawContactsSelect = "SELECT "
13194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + RawContacts._ID + ","
13204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.CONTACT_ID + ", "
13214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.AGGREGATION_MODE + ", "
132297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + RawContacts.RAW_CONTACT_IS_READ_ONLY + ", "
13234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.DELETED + ", "
13245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_SOURCE  + ", "
13255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_PRIMARY  + ", "
13265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_ALTERNATIVE  + ", "
13275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.PHONETIC_NAME  + ", "
13285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.PHONETIC_NAME_STYLE  + ", "
13295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.SORT_KEY_PRIMARY  + ", "
13305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.SORT_KEY_ALTERNATIVE + ", "
13314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + rawContactOptionColumns + ", "
13324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + syncColumns
13334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS;
13344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_CONTACTS_ALL + " AS " + rawContactsSelect);
13364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_CONTACTS_RESTRICTED + " AS " + rawContactsSelect
13374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " WHERE " + RawContacts.IS_RESTRICTED + "=0");
13384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactsColumns =
13404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.CONCRETE_CUSTOM_RINGTONE
13414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.CUSTOM_RINGTONE + ", "
13425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + contactNameColumns + ", "
13433d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + baseContactColumns + ", "
13444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_LAST_TIME_CONTACTED
13454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.LAST_TIME_CONTACTED + ", "
13464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL
13474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.SEND_TO_VOICEMAIL + ", "
13484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_STARRED
13494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.STARRED + ", "
13504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_TIMES_CONTACTED
13513d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        + " AS " + Contacts.TIMES_CONTACTED;
13524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactsSelect = "SELECT "
13544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_ID + " AS " + Contacts._ID + ","
13553d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + contactsColumns + ", "
13563d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(ContactsColumns.CONCRETE_ID, Contacts.PHOTO_URI) + ", "
13573d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(ContactsColumns.CONCRETE_ID, Contacts.PHOTO_THUMBNAIL_URI)
13584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.CONTACTS
1359fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1360fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")";
13614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.CONTACTS_ALL + " AS " + contactsSelect);
1363fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.CONTACTS_RESTRICTED + " AS " + contactsSelect
1364fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " WHERE " + ContactsColumns.SINGLE_IS_RESTRICTED + "=0");
1365a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1366a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        String rawEntitiesSelect = "SELECT "
1367a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContacts.CONTACT_ID + ", "
1368a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DELETED + " AS " + RawContacts.DELETED + ","
1369a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + dataColumns + ", "
1370a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + syncColumns + ", "
1371a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC1 + ", "
1372a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC2 + ", "
1373a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC3 + ", "
1374a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC4 + ", "
1375a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + RawContacts._ID + ", "
1376a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + RawContacts.Entity.DATA_ID + ","
1377a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_STARRED + " AS " + RawContacts.STARRED + ","
1378a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED + " AS "
1379a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                        + RawContacts.IS_RESTRICTED + ","
1380a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
1381a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS
1382a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.DATA + " ON ("
1383a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1384a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1385a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
1386a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.MIMETYPES + " ON ("
1387a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1388a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
1389a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1390a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1391a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
1392a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1393a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_ENTITIES + " AS "
1394a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + rawEntitiesSelect);
1395a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_ENTITIES_RESTRICTED + " AS "
1396a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + rawEntitiesSelect + " WHERE " + RawContacts.IS_RESTRICTED + "=0");
1397a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1398a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        String entitiesSelect = "SELECT "
1399a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + Contacts._ID + ", "
1400a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + RawContacts.CONTACT_ID + ", "
1401a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DELETED + " AS " + RawContacts.DELETED + ","
1402a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED
1403a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                        + " AS " + RawContacts.IS_RESTRICTED + ","
1404a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + dataColumns + ", "
1405a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + syncColumns + ", "
1406a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + contactsColumns + ", "
14073d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
14083d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_URI) + ", "
14093d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
14103d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_THUMBNAIL_URI) + ", "
1411a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC1 + ", "
1412a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC2 + ", "
1413a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC3 + ", "
1414a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC4 + ", "
1415a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + Contacts.Entity.RAW_CONTACT_ID + ", "
1416a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + Contacts.Entity.DATA_ID + ","
1417a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
1418a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS
1419a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " JOIN " + Tables.CONTACTS + " ON ("
1420a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   RawContactsColumns.CONCRETE_CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID + ")"
1421a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1422a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")"
1423a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.DATA + " ON ("
1424a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1425a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1426a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
1427a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.MIMETYPES + " ON ("
1428a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1429a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
1430a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1431a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1432a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
1433a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1434a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.ENTITIES + " AS "
1435a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + entitiesSelect);
1436a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.ENTITIES_RESTRICTED + " AS "
1437a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + entitiesSelect + " WHERE " + RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0");
1438a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    }
14394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
14403d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    private static String buildPhotoUriAlias(String contactIdColumn, String alias) {
14412b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        return "(CASE WHEN " + Contacts.PHOTO_ID + " IS NULL"
14422b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " OR " + Contacts.PHOTO_ID + "=0"
14432b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " THEN NULL"
14442b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " ELSE " + "'" + Contacts.CONTENT_URI + "/'||"
14452b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                        + contactIdColumn + "|| '/" + Photo.CONTENT_DIRECTORY + "'"
14462b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " END)"
14472b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " AS " + alias;
14483d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
14493d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
1450a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    private static void createGroupsView(SQLiteDatabase db) {
1451a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.GROUPS_ALL + ";");
145289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        String groupsColumns =
145389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                Groups.ACCOUNT_NAME + ","
145489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.ACCOUNT_TYPE + ","
145589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SOURCE_ID + ","
145689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.VERSION + ","
145789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.DIRTY + ","
145889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.TITLE + ","
145989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.TITLE_RES + ","
146089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.NOTES + ","
146189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYSTEM_ID + ","
146289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.DELETED + ","
146389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.GROUP_VISIBLE + ","
146489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SHOULD_SYNC + ","
1465dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + Groups.AUTO_ADD + ","
1466dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + Groups.FAVORITES + ","
1467c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                + Groups.GROUP_IS_READ_ONLY + ","
146889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC1 + ","
146989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC2 + ","
147089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC3 + ","
147189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC4 + ","
147289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + PackagesColumns.PACKAGE + " AS " + Groups.RES_PACKAGE;
147389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
147489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        String groupsSelect = "SELECT "
147589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + GroupsColumns.CONCRETE_ID + " AS " + Groups._ID + ","
147689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + groupsColumns
147789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + " FROM " + Tables.GROUPS_JOIN_PACKAGES;
147889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
147989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.GROUPS_ALL + " AS " + groupsSelect);
1480b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
1481b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1482b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
1483b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
148446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion < 99) {
148546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion
148646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana                    + ", data will be lost!");
148746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
148846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.CONTACTS + ";");
148946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.RAW_CONTACTS + ";");
149046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.PACKAGES + ";");
149146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.MIMETYPES + ";");
149246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.DATA + ";");
149346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.PHONE_LOOKUP + ";");
149446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.NAME_LOOKUP + ";");
149546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.NICKNAME_LOOKUP + ";");
149646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.GROUPS + ";");
149746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.ACTIVITIES + ";");
149846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.CALLS + ";");
149946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.SETTINGS + ";");
150046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.STATUS_UPDATES + ";");
150146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
150246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // TODO: we should not be dropping agg_exceptions and contact_options. In case that
150346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // table's schema changes, we should try to preserve the data, because it was entered
150446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // by the user and has never been synched to the server.
150546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.AGGREGATION_EXCEPTIONS + ";");
150646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
150746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            onCreate(db);
150846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            return;
150946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
1510f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
151146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion);
1512a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
151308e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        boolean upgradeViewsAndTriggers = false;
151404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        boolean upgradeNameLookup = false;
151508e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov
151646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion == 99) {
151708e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
151846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            oldVersion++;
151946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
152046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
1521a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        if (oldVersion == 100) {
1522a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            db.execSQL("CREATE INDEX IF NOT EXISTS mimetypes_mimetype_index ON "
1523a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                    + Tables.MIMETYPES + " ("
1524a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                            + MimetypesColumns.MIMETYPE + ","
1525a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                            + MimetypesColumns._ID + ");");
1526a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            updateIndexStats(db, Tables.MIMETYPES,
1527a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                    "mimetypes_mimetype_index", "50 1 1");
1528a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
152908e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1530a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            oldVersion++;
1531a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        }
1532a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1533fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        if (oldVersion == 101) {
153408e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1535fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov            oldVersion++;
1536fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        }
1537fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
153847ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov        if (oldVersion == 102) {
153908e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
154047ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov            oldVersion++;
154147ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov        }
154247ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov
154336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        if (oldVersion == 103) {
154408e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1545bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey            oldVersion++;
1546bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey        }
1547bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey
154871037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov        if (oldVersion == 104 || oldVersion == 201) {
154971037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov            LegacyApiSupport.createSettingsTable(db);
155008e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
15513410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov            oldVersion++;
15523410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov        }
15533410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov
155471037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov        if (oldVersion == 105) {
15555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion202(db);
155604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            upgradeNameLookup = true;
15573410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov            oldVersion = 202;
155836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        }
155936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
1560fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        if (oldVersion == 202) {
15615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion203(db);
156208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1563fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov            oldVersion++;
1564fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        }
1565fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
15669b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori        if (oldVersion == 203) {
156708e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
15689b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori            oldVersion++;
15699b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori        }
15709b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori
15715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (oldVersion == 204) {
15725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion205(db);
157308e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
15745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            oldVersion++;
15755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
15765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
1577f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        if (oldVersion == 205) {
1578f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            upgrateToVersion206(db);
1579f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1580f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            oldVersion++;
1581f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        }
1582f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov
158331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        if (oldVersion == 206) {
1584b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeToVersion300(db);
158534469970fb04b9b188b5430f592b0c956a6ea2aaDmitri Plotnikov            oldVersion = 300;
158631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
158731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
15886c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        if (oldVersion == 300) {
15896c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook            upgradeViewsAndTriggers = true;
15906c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook            oldVersion = 301;
15916c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        }
15926c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook
1593916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        if (oldVersion == 301) {
1594916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1595916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            oldVersion = 302;
1596916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        }
1597916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov
1598b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (oldVersion == 302) {
1599b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeEmailToVersion303(db);
1600b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeNicknameToVersion303(db);
1601b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            oldVersion = 303;
1602b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
1603b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
160408768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        if (oldVersion == 303) {
160508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            upgradeToVersion304(db);
160608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            oldVersion = 304;
160708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        }
160808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
1609f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        if (oldVersion == 304) {
1610f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee            upgradeNameLookup = true;
1611f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee            oldVersion = 305;
1612f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        }
1613f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee
161460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        if (oldVersion == 305) {
161560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            upgradeToVersion306(db);
161660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            oldVersion = 306;
161760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        }
161860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
1619b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        if (oldVersion == 306) {
1620b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            upgradeToVersion307(db);
1621b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            oldVersion = 307;
1622b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        }
1623b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
1624743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        if (oldVersion == 307) {
1625743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov            upgradeToVersion308(db);
1626743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov            oldVersion = 308;
1627743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        }
1628743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
162994c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        // Gingerbread upgrades
163094c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        if (oldVersion < 350) {
1631afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann            upgradeViewsAndTriggers = true;
163294c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            oldVersion = 351;
1633afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann        }
1634afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann
163594c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        if (oldVersion == 351) {
163694c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            upgradeNameLookup = true;
163794c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            oldVersion = 352;
163880d7871ca31d604cbfd857661d5300bb090076dbDaniel Lehmann        }
163980d7871ca31d604cbfd857661d5300bb090076dbDaniel Lehmann
16407da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        if (oldVersion == 352) {
16417da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            upgradeToVersion353(db);
16427da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            oldVersion = 353;
16437da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        }
16447da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
1645f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        // Honeycomb upgrades
1646f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        if (oldVersion < 400) {
1647dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana            upgradeViewsAndTriggers = true;
1648f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov            upgradeToVersion400(db);
1649f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov            oldVersion = 400;
1650dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        }
1651dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana
1652f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        if (oldVersion == 400) {
16534394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            upgradeViewsAndTriggers = true;
16544394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            upgradeToVersion401(db);
16554394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            oldVersion = 401;
16564394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        }
16574394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
1658d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        if (oldVersion == 401) {
1659d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov            upgradeToVersion402(db);
1660d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov            oldVersion = 402;
1661d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        }
1662d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
166397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        if (oldVersion == 402) {
166497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            upgradeViewsAndTriggers = true;
166597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            upgradeToVersion403(db);
166697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            oldVersion = 403;
166797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        }
166897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
1669a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        if (oldVersion == 403) {
1670a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1671a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov            oldVersion = 404;
1672a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        }
1673a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1674892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (oldVersion == 404) {
1675892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1676892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            upgradeToVersion405(db);
1677892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            oldVersion = 405;
1678892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
1679892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
16802530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        if (oldVersion == 405) {
16812530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            upgradeViewsAndTriggers = true;
16822530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            upgradeToVersion406(db);
16832530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            oldVersion = 406;
16842530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        }
16852530512f639c4979fd7371c7dd25dd67e8118124Bai Tao
1686cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov        if (oldVersion == 406) {
1687cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1688cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov            oldVersion = 407;
1689cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov        }
1690cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov
1691385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        if (oldVersion == 407) {
1692d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            // Obsolete
1693385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            oldVersion = 408;
1694385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        }
1695385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
16963d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        if (oldVersion == 408) {
16973d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            upgradeViewsAndTriggers = true;
16983d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            upgradeToVersion409(db);
16993d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            oldVersion = 409;
17003d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        }
17013d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
17022b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        if (oldVersion == 409) {
17032b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov            upgradeViewsAndTriggers = true;
17042b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov            oldVersion = 410;
17052b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        }
17062b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov
1707d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        if (oldVersion == 410) {
1708d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            upgradeToVersion411(db);
1709d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            oldVersion = 411;
1710d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        }
1711d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov
17127da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        if (oldVersion == 411) {
17137da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            // Same upgrade as 353, only on Honeycomb devices
17147da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            upgradeToVersion353(db);
17157da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            oldVersion = 412;
17167da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        }
17177da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
1718e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov        if (oldVersion == 412) {
1719e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov            upgradeToVersion413(db);
1720e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov            oldVersion = 413;
1721e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov        }
1722e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov
172356f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee        if (oldVersion == 413) {
172456f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee            upgradeNameLookup = true;
172556f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee            oldVersion = 414;
172656f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee        }
172756f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee
1728c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        if (oldVersion == 414) {
1729c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            upgradeToVersion415(db);
1730c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1731c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            oldVersion = 415;
1732c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        }
1733c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov
173408e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        if (upgradeViewsAndTriggers) {
173508e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createContactsViews(db);
173608e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createGroupsView(db);
173708e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createContactsTriggers(db);
1738916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            createContactsIndexes(db);
173908e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            LegacyApiSupport.createViews(db);
1740916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            updateSqliteStats(db);
1741916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            mReopenDatabase = true;
174208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        }
174308e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov
174404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (upgradeNameLookup) {
174504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            rebuildNameLookup(db);
174604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
174704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
174846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion != newVersion) {
174946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            throw new IllegalStateException(
175046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana                    "error upgrading the database to version " + newVersion);
175146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
1752b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
1753b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
17545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion202(SQLiteDatabase db) {
175536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL(
175636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "ALTER TABLE " + Tables.PHONE_LOOKUP +
175736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " ADD " + PhoneLookupColumns.MIN_MATCH + " TEXT;");
175836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
175936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
176036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
176136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
176236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
176336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        ");");
176436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
176536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        updateIndexStats(db, Tables.PHONE_LOOKUP,
176636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "phone_lookup_min_match_index", "10000 2 2 1");
176736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
176836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        SQLiteStatement update = db.compileStatement(
176936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "UPDATE " + Tables.PHONE_LOOKUP +
177036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " SET " + PhoneLookupColumns.MIN_MATCH + "=?" +
177136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " WHERE " + PhoneLookupColumns.DATA_ID + "=?");
177236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
177336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        // Populate the new column
177436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        Cursor c = db.query(Tables.PHONE_LOOKUP + " JOIN " + Tables.DATA +
177536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " ON (" + PhoneLookupColumns.DATA_ID + "=" + DataColumns.CONCRETE_ID + ")",
177636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                new String[]{Data._ID, Phone.NUMBER}, null, null, null, null, null);
177736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        try {
177836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            while (c.moveToNext()) {
177936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                long dataId = c.getLong(0);
178036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                String number = c.getString(1);
178136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                if (!TextUtils.isEmpty(number)) {
178236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.bindString(1, PhoneNumberUtils.toCallerIDMinMatch(number));
178336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.bindLong(2, dataId);
178436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.execute();
178536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                }
178636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            }
178736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        } finally {
178836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            c.close();
178936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        }
179036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    }
179136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
17925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion203(SQLiteDatabase db) {
1793758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // Garbage-collect first. A bug in Eclair was sometimes leaving
1794758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // raw_contacts in the database that no longer had contacts associated
1795758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // with them.  To avoid failures during this database upgrade, drop
1796758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // the orphaned raw_contacts.
1797758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        db.execSQL(
1798758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                "DELETE FROM raw_contacts" +
1799758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                " WHERE contact_id NOT NULL" +
1800758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                " AND contact_id NOT IN (SELECT _id FROM contacts)");
1801758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov
1802fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1803fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "ALTER TABLE " + Tables.CONTACTS +
1804fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " ADD " + Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)");
1805fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1806fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "ALTER TABLE " + Tables.RAW_CONTACTS +
18074394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " ADD contact_in_visible_group INTEGER NOT NULL DEFAULT 0");
1808fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1809fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // For each Contact, find the RawContact that contributed the display name
1810fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1811fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1812fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.NAME_RAW_CONTACT_ID + "=(" +
1813fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " SELECT " + RawContacts._ID +
1814fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.RAW_CONTACTS +
1815fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
1816fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " AND " + RawContactsColumns.CONCRETE_DISPLAY_NAME + "=" +
1817fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                                Tables.CONTACTS + "." + Contacts.DISPLAY_NAME +
1818fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " ORDER BY " + RawContacts._ID +
1819fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " LIMIT 1)"
1820fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1821fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1822fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_name_raw_contact_id_index ON " + Tables.CONTACTS + " (" +
1823fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID +
1824fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1825fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1826fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // If for some unknown reason we missed some names, let's make sure there are
1827fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // no contacts without a name, picking a raw contact "at random".
1828fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1829fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1830fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.NAME_RAW_CONTACT_ID + "=(" +
1831fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " SELECT " + RawContacts._ID +
1832fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.RAW_CONTACTS +
1833fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
1834fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " ORDER BY " + RawContacts._ID +
1835fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " LIMIT 1)" +
1836fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " WHERE " + Contacts.NAME_RAW_CONTACT_ID + " IS NULL"
1837fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1838fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1839fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // Wipe out DISPLAY_NAME on the Contacts table as it is no longer in use.
1840fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1841fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1842fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.DISPLAY_NAME + "=NULL"
1843fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1844fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1845fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // Copy the IN_VISIBLE_GROUP flag down to all raw contacts to allow
1846fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // indexing on (display_name, in_visible_group)
1847fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1848fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.RAW_CONTACTS +
18494394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " SET contact_in_visible_group=(" +
1850fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        "SELECT " + Contacts.IN_VISIBLE_GROUP +
1851fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.CONTACTS +
1852bcbd6a5cdd2d1aa6531c592428dc20e0282486c3Dmitri Plotnikov                        " WHERE " + Contacts._ID + "=" + RawContacts.CONTACT_ID + ")" +
1853bcbd6a5cdd2d1aa6531c592428dc20e0282486c3Dmitri Plotnikov                " WHERE " + RawContacts.CONTACT_ID + " NOT NULL"
1854fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1855fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1856fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
18574394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
1858fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                RawContactsColumns.DISPLAY_NAME + " COLLATE LOCALIZED ASC" +
1859fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1860fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1861fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("DROP INDEX contacts_visible_index");
1862fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_visible_index ON " + Tables.CONTACTS + " (" +
1863fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.IN_VISIBLE_GROUP +
1864fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1865fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov    }
1866fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
18675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion205(SQLiteDatabase db) {
18685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
18695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.DISPLAY_NAME_ALTERNATIVE + " TEXT;");
18705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
18715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.PHONETIC_NAME + " TEXT;");
18725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
18735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.PHONETIC_NAME_STYLE + " INTEGER;");
18745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
1875de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " ADD " + RawContacts.SORT_KEY_PRIMARY
1876de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " TEXT COLLATE " + ContactsProvider2.PHONEBOOK_COLLATOR_NAME + ";");
18775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
1878de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " ADD " + RawContacts.SORT_KEY_ALTERNATIVE
1879de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " TEXT COLLATE " + ContactsProvider2.PHONEBOOK_COLLATOR_NAME + ";");
18805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        final Locale locale = Locale.getDefault();
18825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
188351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        NameSplitter splitter = createNameSplitter();
18845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement rawContactUpdate = db.compileStatement(
18865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.RAW_CONTACTS +
18875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
18885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.DISPLAY_NAME_PRIMARY + "=?," +
18895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," +
18905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.PHONETIC_NAME + "=?," +
18915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.PHONETIC_NAME_STYLE + "=?," +
18925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.SORT_KEY_PRIMARY + "=?," +
18935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.SORT_KEY_ALTERNATIVE + "=?" +
18945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + RawContacts._ID + "=?");
18955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        upgradeStructuredNamesToVersion205(db, rawContactUpdate, splitter);
18975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        upgradeOrganizationsToVersion205(db, rawContactUpdate, splitter);
18985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("DROP INDEX raw_contact_sort_key1_index");
19005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
19014394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
19025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.SORT_KEY_PRIMARY +
19035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        ");");
19045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key2_index ON " + Tables.RAW_CONTACTS + " (" +
19064394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
19075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.SORT_KEY_ALTERNATIVE +
19085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        ");");
19095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
19105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private interface StructName205Query {
19125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String TABLE = Tables.DATA_JOIN_RAW_CONTACTS;
19135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String COLUMNS[] = {
19155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.CONCRETE_ID,
19165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Data.RAW_CONTACT_ID,
19175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_SOURCE,
19185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_PRIMARY,
19195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PREFIX,
19205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.GIVEN_NAME,
19215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.MIDDLE_NAME,
19225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.FAMILY_NAME,
19235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.SUFFIX,
19245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_FAMILY_NAME,
19255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_MIDDLE_NAME,
19265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_GIVEN_NAME,
19275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        };
19285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int ID = 0;
19305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int RAW_CONTACT_ID = 1;
19315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int DISPLAY_NAME_SOURCE = 2;
19325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int DISPLAY_NAME = 3;
19335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PREFIX = 4;
19345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int GIVEN_NAME = 5;
19355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int MIDDLE_NAME = 6;
19365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int FAMILY_NAME = 7;
19375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int SUFFIX = 8;
19385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_FAMILY_NAME = 9;
19395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_MIDDLE_NAME = 10;
19405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_GIVEN_NAME = 11;
19415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
19425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeStructuredNamesToVersion205(SQLiteDatabase db,
19445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement rawContactUpdate, NameSplitter splitter) {
19455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        // Process structured names to detect the style of the full name and phonetic name
19475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        long mMimeType;
19495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
19505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            mMimeType = DatabaseUtils.longForQuery(db,
19515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    "SELECT " + MimetypesColumns._ID +
19525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    " FROM " + Tables.MIMETYPES +
19535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    " WHERE " + MimetypesColumns.MIMETYPE
19545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                            + "='" + StructuredName.CONTENT_ITEM_TYPE + "'", null);
19555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } catch (SQLiteDoneException e) {
19565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            // No structured names in the database
19575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            return;
19585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
19595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement structuredNameUpdate = db.compileStatement(
19615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.DATA +
19625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
19635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.FULL_NAME_STYLE + "=?," +
19645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.DISPLAY_NAME + "=?," +
19655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.PHONETIC_NAME_STYLE + "=?" +
19665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + Data._ID + "=?");
19675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        NameSplitter.Name name = new NameSplitter.Name();
19695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        StringBuilder sb = new StringBuilder();
19705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        Cursor cursor = db.query(StructName205Query.TABLE,
19715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructName205Query.COLUMNS,
19725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=" + mMimeType, null, null, null, null);
19735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
19745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            while (cursor.moveToNext()) {
19755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long dataId = cursor.getLong(StructName205Query.ID);
19765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long rawContactId = cursor.getLong(StructName205Query.RAW_CONTACT_ID);
19775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                int displayNameSource = cursor.getInt(StructName205Query.DISPLAY_NAME_SOURCE);
19785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String displayName = cursor.getString(StructName205Query.DISPLAY_NAME);
19795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.clear();
19815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.prefix = cursor.getString(StructName205Query.PREFIX);
19825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.givenNames = cursor.getString(StructName205Query.GIVEN_NAME);
19835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.middleName = cursor.getString(StructName205Query.MIDDLE_NAME);
19845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.familyName = cursor.getString(StructName205Query.FAMILY_NAME);
19855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.suffix = cursor.getString(StructName205Query.SUFFIX);
19865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticFamilyName = cursor.getString(StructName205Query.PHONETIC_FAMILY_NAME);
19875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticMiddleName = cursor.getString(StructName205Query.PHONETIC_MIDDLE_NAME);
19885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticGivenName = cursor.getString(StructName205Query.PHONETIC_GIVEN_NAME);
19895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                upgradeNameToVersion205(dataId, rawContactId, displayNameSource, displayName, name,
19915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        structuredNameUpdate, rawContactUpdate, splitter, sb);
19925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
19935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } finally {
19945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            cursor.close();
19955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
19965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
19975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeNameToVersion205(long dataId, long rawContactId, int displayNameSource,
19995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String currentDisplayName, NameSplitter.Name name,
20005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement structuredNameUpdate, SQLiteStatement rawContactUpdate,
20015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            NameSplitter splitter, StringBuilder sb) {
20025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        splitter.guessNameStyle(name);
2004ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        int unadjustedFullNameStyle = name.fullNameStyle;
20055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        name.fullNameStyle = splitter.getAdjustedFullNameStyle(name.fullNameStyle);
20065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String displayName = splitter.join(name, true);
20075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
2008ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        // Don't update database with the adjusted fullNameStyle as it is locale
2009ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        // related
2010ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        structuredNameUpdate.bindLong(1, unadjustedFullNameStyle);
20115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        DatabaseUtils.bindObjectToProgram(structuredNameUpdate, 2, displayName);
20125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.bindLong(3, name.phoneticNameStyle);
20135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.bindLong(4, dataId);
20145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.execute();
20155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (displayNameSource == DisplayNameSources.STRUCTURED_NAME) {
20175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String displayNameAlternative = splitter.join(name, false);
20185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String phoneticName = splitter.joinPhoneticName(name);
20195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String sortKey = null;
20205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String sortKeyAlternative = null;
20215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            if (phoneticName != null) {
20235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKey = sortKeyAlternative = phoneticName;
2024ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao            } else if (name.fullNameStyle == FullNameStyle.CHINESE ||
2025ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                    name.fullNameStyle == FullNameStyle.CJK) {
2026ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                sortKey = sortKeyAlternative = ContactLocaleUtils.getIntance()
2027ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                        .getSortKey(displayName, name.fullNameStyle);
20285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
20295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            if (sortKey == null) {
20315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKey = displayName;
20325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKeyAlternative = displayNameAlternative;
20335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
20345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            updateRawContact205(rawContactUpdate, rawContactId, displayName,
20365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    displayNameAlternative, name.phoneticNameStyle, phoneticName, sortKey,
20375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    sortKeyAlternative);
20385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
20395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
20405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private interface Organization205Query {
20425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String TABLE = Tables.DATA_JOIN_RAW_CONTACTS;
20435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String COLUMNS[] = {
20455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.CONCRETE_ID,
20465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Data.RAW_CONTACT_ID,
20475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Organization.COMPANY,
20485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Organization.PHONETIC_NAME,
20495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        };
20505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int ID = 0;
20525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int RAW_CONTACT_ID = 1;
20535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int COMPANY = 2;
20545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_NAME = 3;
20555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
20565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeOrganizationsToVersion205(SQLiteDatabase db,
20585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement rawContactUpdate, NameSplitter splitter) {
2059b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeType = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
20605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement organizationUpdate = db.compileStatement(
20625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.DATA +
20635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
20645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        Organization.PHONETIC_NAME_STYLE + "=?" +
20655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + Data._ID + "=?");
20665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        Cursor cursor = db.query(Organization205Query.TABLE, Organization205Query.COLUMNS,
2068b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=" + mimeType + " AND "
20695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + RawContacts.DISPLAY_NAME_SOURCE + "=" + DisplayNameSources.ORGANIZATION,
20705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                null, null, null, null);
20715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
20725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            while (cursor.moveToNext()) {
20735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long dataId = cursor.getLong(Organization205Query.ID);
20745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long rawContactId = cursor.getLong(Organization205Query.RAW_CONTACT_ID);
20755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String company = cursor.getString(Organization205Query.COMPANY);
20765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String phoneticName = cursor.getString(Organization205Query.PHONETIC_NAME);
20775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                int phoneticNameStyle = splitter.guessPhoneticNameStyle(phoneticName);
20795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.bindLong(1, phoneticNameStyle);
20815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.bindLong(2, dataId);
20825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.execute();
20835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String sortKey = null;
20855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                if (phoneticName == null && company != null) {
20865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    int nameStyle = splitter.guessFullNameStyle(company);
20875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    nameStyle = splitter.getAdjustedFullNameStyle(nameStyle);
2088ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                    if (nameStyle == FullNameStyle.CHINESE ||
2089ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                            nameStyle == FullNameStyle.CJK ) {
2090ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                        sortKey = ContactLocaleUtils.getIntance()
2091ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                                .getSortKey(company, nameStyle);
20925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    }
20935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                }
20945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                if (sortKey == null) {
20965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    sortKey = company;
20975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                }
20985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                updateRawContact205(rawContactUpdate, rawContactId, company,
21005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        company, phoneticNameStyle, phoneticName, sortKey, sortKey);
21015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
21025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } finally {
21035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            cursor.close();
21045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
21055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
21065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
21075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void updateRawContact205(SQLiteStatement rawContactUpdate, long rawContactId,
21085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String displayName, String displayNameAlternative, int phoneticNameStyle,
21095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String phoneticName, String sortKeyPrimary, String sortKeyAlternative) {
21105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 1, displayName);
21115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 2, displayNameAlternative);
21125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 3, phoneticName);
21135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.bindLong(4, phoneticNameStyle);
21145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 5, sortKeyPrimary);
21155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 6, sortKeyAlternative);
21165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.bindLong(7, rawContactId);
21175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.execute();
21185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
21195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
2120f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov    private void upgrateToVersion206(SQLiteDatabase db) {
2121f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
2122f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                + " ADD " + RawContacts.NAME_VERIFIED + " INTEGER NOT NULL DEFAULT 0;");
2123f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov    }
2124f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov
212531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    private interface Organization300Query {
212631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String TABLE = Tables.DATA;
212731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
212831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String SELECTION = DataColumns.MIMETYPE_ID + "=?";
212931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
213031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String COLUMNS[] = {
213131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization._ID,
213231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.RAW_CONTACT_ID,
213331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.COMPANY,
213431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.TITLE
213531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        };
213631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
213731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int ID = 0;
213831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int RAW_CONTACT_ID = 1;
213931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int COMPANY = 2;
214031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int TITLE = 3;
214131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    }
214231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
214331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    /**
214431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     * Fix for the bug where name lookup records for organizations would get removed by
214531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     * unrelated updates of the data rows.
214631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     */
2147b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeToVersion300(SQLiteDatabase db) {
2148b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeType = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
2149b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeType == -1) {
215031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            return;
215131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
215231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
215331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        ContentValues values = new ContentValues();
215431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
215531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        // Find all data rows with the mime type "organization"
215631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        Cursor cursor = db.query(Organization300Query.TABLE, Organization300Query.COLUMNS,
2157b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Organization300Query.SELECTION, new String[] {String.valueOf(mimeType)},
215831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                null, null, null);
215931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        try {
216031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            while (cursor.moveToNext()) {
216131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                long dataId = cursor.getLong(Organization300Query.ID);
216231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                long rawContactId = cursor.getLong(Organization300Query.RAW_CONTACT_ID);
216331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                String company = cursor.getString(Organization300Query.COMPANY);
216431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                String title = cursor.getString(Organization300Query.TITLE);
216531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
216631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                // First delete name lookup if there is any (chances are there won't be)
216731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                db.delete(Tables.NAME_LOOKUP, NameLookupColumns.DATA_ID + "=?",
216831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                        new String[]{String.valueOf(dataId)});
216931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
217031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                // Now insert two name lookup records: one for company name, one for title
217131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.DATA_ID, dataId);
217231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
217331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.NAME_TYPE, NameLookupType.ORGANIZATION);
217431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
217531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                if (!TextUtils.isEmpty(company)) {
217631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME,
217731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                            NameNormalizer.normalize(company));
217831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
217931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                }
218031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
218131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                if (!TextUtils.isEmpty(title)) {
218231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME,
218331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                            NameNormalizer.normalize(title));
218431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
218531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                }
218631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            }
218731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        } finally {
218831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            cursor.close();
218931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
219031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    }
219131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
2192b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private static final class Upgrade303Query {
2193b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
2194b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2195b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String SELECTION =
2196b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=?" +
2197b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    " AND " + Data._ID + " NOT IN " +
2198b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    "(SELECT " + NameLookupColumns.DATA_ID + " FROM " + Tables.NAME_LOOKUP + ")" +
2199b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    " AND " + Data.DATA1 + " NOT NULL";
2200b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2201b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String COLUMNS[] = {
2202b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data._ID,
2203b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data.RAW_CONTACT_ID,
2204b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data.DATA1,
2205b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        };
2206b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2207b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int ID = 0;
2208b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
2209b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int DATA1 = 2;
2210b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2211b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2212b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    /**
2213b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * The {@link ContactsProvider2#update} method was deleting name lookup for new
2214b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * emails during the sync.  We need to restore the lost name lookup rows.
2215b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     */
2216b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeEmailToVersion303(SQLiteDatabase db) {
2217b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Email.CONTENT_ITEM_TYPE);
2218b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeTypeId == -1) {
2219b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return;
2220b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2221b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2222b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        ContentValues values = new ContentValues();
2223b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2224b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        // Find all data rows with the mime type "email" that are missing name lookup
2225b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Cursor cursor = db.query(Upgrade303Query.TABLE, Upgrade303Query.COLUMNS,
2226b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Upgrade303Query.SELECTION, new String[] {String.valueOf(mimeTypeId)},
2227b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                null, null, null);
2228b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2229b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            while (cursor.moveToNext()) {
2230b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long dataId = cursor.getLong(Upgrade303Query.ID);
2231b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long rawContactId = cursor.getLong(Upgrade303Query.RAW_CONTACT_ID);
2232b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                String value = cursor.getString(Upgrade303Query.DATA1);
2233b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                value = extractHandleFromEmailAddress(value);
2234b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2235b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                if (value != null) {
2236b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.DATA_ID, dataId);
2237b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
2238b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.NAME_TYPE, NameLookupType.EMAIL_BASED_NICKNAME);
2239b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME, NameNormalizer.normalize(value));
2240b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
2241b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                }
2242b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            }
2243b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } finally {
2244b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            cursor.close();
2245b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2246b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2247b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2248b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    /**
2249b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * The {@link ContactsProvider2#update} method was deleting name lookup for new
2250b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * nicknames during the sync.  We need to restore the lost name lookup rows.
2251b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     */
2252b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeNicknameToVersion303(SQLiteDatabase db) {
2253b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Nickname.CONTENT_ITEM_TYPE);
2254b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeTypeId == -1) {
2255b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return;
2256b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2257b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2258b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        ContentValues values = new ContentValues();
2259b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2260b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        // Find all data rows with the mime type "nickname" that are missing name lookup
2261b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Cursor cursor = db.query(Upgrade303Query.TABLE, Upgrade303Query.COLUMNS,
2262b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Upgrade303Query.SELECTION, new String[] {String.valueOf(mimeTypeId)},
2263b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                null, null, null);
2264b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2265b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            while (cursor.moveToNext()) {
2266b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long dataId = cursor.getLong(Upgrade303Query.ID);
2267b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long rawContactId = cursor.getLong(Upgrade303Query.RAW_CONTACT_ID);
2268b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                String value = cursor.getString(Upgrade303Query.DATA1);
2269b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2270b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.DATA_ID, dataId);
2271b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
2272b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.NAME_TYPE, NameLookupType.NICKNAME);
2273b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.NORMALIZED_NAME, NameNormalizer.normalize(value));
2274b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                db.insert(Tables.NAME_LOOKUP, null, values);
2275b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            }
2276b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } finally {
2277b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            cursor.close();
2278b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2279b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2280b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
228151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void upgradeToVersion304(SQLiteDatabase db) {
228251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        // Mimetype table requires an index on mime type
228351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS mime_type ON " + Tables.MIMETYPES + " (" +
228451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                MimetypesColumns.MIMETYPE +
228551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        ");");
228651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
228751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
228860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann    private void upgradeToVersion306(SQLiteDatabase db) {
228960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        // Fix invalid lookup that was used for Exchange contacts (it was not escaped)
229060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        // It happened when a new contact was created AND synchronized
229160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final StringBuilder lookupKeyBuilder = new StringBuilder();
229260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final SQLiteStatement updateStatement = db.compileStatement(
229360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "UPDATE contacts " +
229460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "SET lookup=? " +
229560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "WHERE _id=?");
229660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final Cursor contactIdCursor = db.rawQuery(
229760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "SELECT DISTINCT contact_id " +
229860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "FROM raw_contacts " +
229960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "WHERE deleted=0 AND account_type='com.android.exchange'",
230060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                null);
230160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        try {
230260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            while (contactIdCursor.moveToNext()) {
230360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                final long contactId = contactIdCursor.getLong(0);
230460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                lookupKeyBuilder.setLength(0);
230560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                final Cursor c = db.rawQuery(
230660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "SELECT account_type, account_name, _id, sourceid, display_name " +
230760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "FROM raw_contacts " +
230860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "WHERE contact_id=? " +
230960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "ORDER BY _id",
231060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        new String[] { String.valueOf(contactId) });
231160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                try {
231260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    while (c.moveToNext()) {
231360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        ContactLookupKey.appendToLookupKey(lookupKeyBuilder,
231460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(0),
231560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(1),
231660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getLong(2),
231760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(3),
231860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(4));
231960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    }
232060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                } finally {
232160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    c.close();
232260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                }
232360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
232460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                if (lookupKeyBuilder.length() == 0) {
232560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    updateStatement.bindNull(1);
232660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                } else {
232760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    updateStatement.bindString(1, Uri.encode(lookupKeyBuilder.toString()));
232860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                }
232960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                updateStatement.bindLong(2, contactId);
233060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
233160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                updateStatement.execute();
233260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            }
233360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        } finally {
233460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            updateStatement.close();
233560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            contactIdCursor.close();
233660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        }
233760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann    }
233860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
2339b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    private void upgradeToVersion307(SQLiteDatabase db) {
2340b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        db.execSQL("CREATE TABLE properties (" +
2341b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                "property_key TEXT PRIMARY_KEY, " +
2342b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                "property_value TEXT" +
2343b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ");");
2344b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
2345b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
2346743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov    private void upgradeToVersion308(SQLiteDatabase db) {
23474394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE accounts (" +
23484394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "account_name TEXT, " +
23494394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "account_type TEXT " +
23504394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
2351743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
23524394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO accounts " +
23534394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "SELECT DISTINCT account_name, account_type FROM raw_contacts");
2354743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov    }
2355743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
2356f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov    private void upgradeToVersion400(SQLiteDatabase db) {
2357dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        db.execSQL("ALTER TABLE " + Tables.GROUPS
2358dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + " ADD " + Groups.FAVORITES + " INTEGER NOT NULL DEFAULT 0;");
2359dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        db.execSQL("ALTER TABLE " + Tables.GROUPS
2360dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + " ADD " + Groups.AUTO_ADD + " INTEGER NOT NULL DEFAULT 0;");
2361dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana    }
2362dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana
23637da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov    private void upgradeToVersion353(SQLiteDatabase db) {
23647da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        db.execSQL("DELETE FROM contacts " +
23657da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov                "WHERE NOT EXISTS (SELECT 1 FROM raw_contacts WHERE contact_id=contacts._id)");
23667da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov    }
23677da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
236851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void rebuildNameLookup(SQLiteDatabase db) {
236951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
237051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        insertNameLookup(db);
237151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        createContactsIndexes(db);
237251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
237351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
237404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
237551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     * Regenerates all locale-sensitive data: nickname_lookup, name_lookup and sort keys.
237604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
237751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    public void setLocale(ContactsProvider2 provider, Locale locale) {
237851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        Log.i(TAG, "Switching to locale " + locale);
237904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
2380c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamilton        long start = SystemClock.uptimeMillis();
238151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
238251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.setLocale(locale);
238351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.beginTransaction();
238451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
238551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX raw_contact_sort_key1_index");
238651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX raw_contact_sort_key2_index");
238751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
238851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
238951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            loadNicknameLookupTable(db);
239051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertNameLookup(db);
239151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            rebuildSortKeys(db, provider);
239251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            createContactsIndexes(db);
239351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.setTransactionSuccessful();
239451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
239551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.endTransaction();
239651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
239751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
2398c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamilton        Log.i(TAG, "Locale change completed in " + (SystemClock.uptimeMillis() - start) + "ms");
239951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
240051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
240151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    /**
240251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     * Regenerates sort keys for all contacts.
240351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     */
240451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void rebuildSortKeys(SQLiteDatabase db, ContactsProvider2 provider) {
240551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        Cursor cursor = db.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID},
240651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                null, null, null, null, null);
240751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
240851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            while (cursor.moveToNext()) {
240951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                long rawContactId = cursor.getLong(0);
241051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                provider.updateRawContactDisplayName(db, rawContactId);
241151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            }
241251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
241351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            cursor.close();
241451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
241551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
241651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
241751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void insertNameLookup(SQLiteDatabase db) {
241804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NAME_LOOKUP);
241904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
242004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        SQLiteStatement nameLookupInsert = db.compileStatement(
242104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                "INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "("
242204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.RAW_CONTACT_ID + ","
242304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.DATA_ID + ","
242404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.NAME_TYPE + ","
242504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.NORMALIZED_NAME +
242604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                ") VALUES (?,?,?,?)");
242704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
242851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
242951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertStructuredNameLookup(db, nameLookupInsert);
243051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertOrganizationLookup(db, nameLookupInsert);
243151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertEmailLookup(db, nameLookupInsert);
243251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertNicknameLookup(db, nameLookupInsert);
243351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
243451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            nameLookupInsert.close();
243551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
243604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
243704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
243804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class StructuredNameQuery {
243904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
244004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
244104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
244204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
244304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
244404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
244504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName._ID,
244604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName.RAW_CONTACT_ID,
244704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName.DISPLAY_NAME,
244804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
244904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
245004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
245104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
245204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int DISPLAY_NAME = 2;
245304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
245404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
245504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private class StructuredNameLookupBuilder extends NameLookupBuilder {
245604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
245704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        private final SQLiteStatement mNameLookupInsert;
245804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        private final CommonNicknameCache mCommonNicknameCache;
245904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
246004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public StructuredNameLookupBuilder(NameSplitter splitter,
246104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                CommonNicknameCache commonNicknameCache, SQLiteStatement nameLookupInsert) {
246204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            super(splitter);
246304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            this.mCommonNicknameCache = commonNicknameCache;
246404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            this.mNameLookupInsert = nameLookupInsert;
246504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
246604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
246704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        @Override
246804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        protected void insertNameLookup(long rawContactId, long dataId, int lookupType,
246904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String name) {
247004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            if (!TextUtils.isEmpty(name)) {
247104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                ContactsDatabaseHelper.this.insertNormalizedNameLookup(mNameLookupInsert,
247204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        rawContactId, dataId, lookupType, name);
247304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
247404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
247504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
247604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        @Override
247704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        protected String[] getCommonNicknameClusters(String normalizedName) {
247804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return mCommonNicknameCache.getCommonNicknameClusters(normalizedName);
247904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
248004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
248104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
248204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
248304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all structured names in the database.
248404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
248504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertStructuredNameLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
2486d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov        NameSplitter nameSplitter = createNameSplitter();
2487d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov        NameLookupBuilder nameLookupBuilder = new StructuredNameLookupBuilder(nameSplitter,
248804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                new CommonNicknameCache(db), nameLookupInsert);
248904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, StructuredName.CONTENT_ITEM_TYPE);
249004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(StructuredNameQuery.TABLE, StructuredNameQuery.COLUMNS,
249104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredNameQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
249204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
249304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
249404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
249504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(StructuredNameQuery.ID);
249604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(StructuredNameQuery.RAW_CONTACT_ID);
249704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String name = cursor.getString(StructuredNameQuery.DISPLAY_NAME);
2498d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov                int fullNameStyle = nameSplitter.guessFullNameStyle(name);
249951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                fullNameStyle = nameSplitter.getAdjustedFullNameStyle(fullNameStyle);
2500d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov                nameLookupBuilder.insertNameLookup(rawContactId, dataId, name, fullNameStyle);
250104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
250204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
250304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
250404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
250504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
250604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
250704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class OrganizationQuery {
250804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
250904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
251004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
251104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
251204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
251304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
251404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization._ID,
251504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.RAW_CONTACT_ID,
251604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.COMPANY,
251704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.TITLE,
251804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
251904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
252004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
252104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
252204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int COMPANY = 2;
252304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int TITLE = 3;
252404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
252504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
252604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
252704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all organizations in the database.
252804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
252904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertOrganizationLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
253004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
253104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(OrganizationQuery.TABLE, OrganizationQuery.COLUMNS,
253204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                OrganizationQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
253304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
253404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
253504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
253604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(OrganizationQuery.ID);
253704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(OrganizationQuery.RAW_CONTACT_ID);
253804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String organization = cursor.getString(OrganizationQuery.COMPANY);
253904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String title = cursor.getString(OrganizationQuery.TITLE);
254004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
254104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.ORGANIZATION, organization);
254204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
254304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.ORGANIZATION, title);
254404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
254504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
254604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
254704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
254804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
254904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
255004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class EmailQuery {
255104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
255204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
255304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
255404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
255504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
255604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
255704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email._ID,
255804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email.RAW_CONTACT_ID,
255904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email.ADDRESS,
256004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
256104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
256204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
256304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
256404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ADDRESS = 2;
256504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
256604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
256704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
256804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all email addresses in the database.
256904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
257004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertEmailLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
257104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Email.CONTENT_ITEM_TYPE);
257204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(EmailQuery.TABLE, EmailQuery.COLUMNS,
257304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                EmailQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
257404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
257504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
257604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
257704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(EmailQuery.ID);
257804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(EmailQuery.RAW_CONTACT_ID);
257904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String address = cursor.getString(EmailQuery.ADDRESS);
258004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                address = extractHandleFromEmailAddress(address);
258104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
258204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.EMAIL_BASED_NICKNAME, address);
258304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
258404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
258504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
258604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
258704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
258804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
258904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class NicknameQuery {
259004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
259104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
259204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
259304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
259404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
259504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
259604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname._ID,
259704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname.RAW_CONTACT_ID,
259804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname.NAME,
259904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
260004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
260104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
260204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
260304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int NAME = 2;
260404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
260504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
260604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
260704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all nicknames in the database.
260804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
260904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertNicknameLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
261004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Nickname.CONTENT_ITEM_TYPE);
261104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(NicknameQuery.TABLE, NicknameQuery.COLUMNS,
261204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                NicknameQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
261304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
261404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
261504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
261604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(NicknameQuery.ID);
261704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(NicknameQuery.RAW_CONTACT_ID);
261804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String nickname = cursor.getString(NicknameQuery.NAME);
261904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
262004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.NICKNAME, nickname);
262104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
262204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
262304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
262404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
262504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
262604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
262704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
262804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts a record in the {@link Tables#NAME_LOOKUP} table.
262904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
263004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    public void insertNameLookup(SQLiteStatement stmt, long rawContactId, long dataId,
263104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            int lookupType, String name) {
263204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (TextUtils.isEmpty(name)) {
263304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return;
263404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
263504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
263604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        String normalized = NameNormalizer.normalize(name);
263704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (TextUtils.isEmpty(normalized)) {
263804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return;
263904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
264004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
264104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        insertNormalizedNameLookup(stmt, rawContactId, dataId, lookupType, normalized);
264204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
264304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
264404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertNormalizedNameLookup(SQLiteStatement stmt, long rawContactId, long dataId,
264504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            int lookupType, String normalizedName) {
264604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(1, rawContactId);
264704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(2, dataId);
264804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(3, lookupType);
264904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindString(4, normalizedName);
265004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.executeInsert();
265104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
265204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
26534394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    /**
26544394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov     * Changing the VISIBLE bit from a field on both RawContacts and Contacts to a separate table.
26554394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov     */
26564394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    private void upgradeToVersion401(SQLiteDatabase db) {
26574394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.VISIBLE_CONTACTS + " (" +
26584394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
26594394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
26604394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.VISIBLE_CONTACTS +
26614394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " SELECT " + Contacts._ID +
26624394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " FROM " + Tables.CONTACTS +
26634394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " WHERE " + Contacts.IN_VISIBLE_GROUP + "!=0");
26644394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("DROP INDEX contacts_visible_index");
26654394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    }
26664394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
2667d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    /**
2668d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov     * Introducing a new table: directories.
2669d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov     */
2670d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    private void upgradeToVersion402(SQLiteDatabase db) {
2671d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        createDirectoriesTable(db);
2672d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    }
2673d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
267497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    private void upgradeToVersion403(SQLiteDatabase db) {
267597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
267697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        createDirectoriesTable(db);
267797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
267897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("ALTER TABLE raw_contacts"
267997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + " ADD raw_contact_is_read_only INTEGER NOT NULL DEFAULT 0;");
268097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
268197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("ALTER TABLE data"
268297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + " ADD is_read_only INTEGER NOT NULL DEFAULT 0;");
268397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    }
268497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
2685892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    private void upgradeToVersion405(SQLiteDatabase db) {
2686892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS phone_lookup;");
2687892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        // Private phone numbers table used for lookup
2688892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" +
2689892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID
2690892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " INTEGER REFERENCES data(_id) NOT NULL," +
2691892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID
2692892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
2693892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL," +
2694892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL" +
2695892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2696892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2697892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" +
2698892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + "," +
2699892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
2700892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
2701892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2702892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2703892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
2704892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
2705892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
2706892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
2707892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2708892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2709892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Phone.CONTENT_ITEM_TYPE);
2710892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (mimeTypeId == -1) {
2711892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            return;
2712892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
2713892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2714892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        String mCountryIso = getCountryIso();
2715892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        Cursor cursor = db.rawQuery(
2716892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    "SELECT _id, " + Phone.RAW_CONTACT_ID + ", " + Phone.NUMBER +
2717892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    " FROM " + Tables.DATA +
2718892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId
2719892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                            + " AND " + Phone.NUMBER + " NOT NULL", null);
2720892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2721892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ContentValues phoneValues = new ContentValues();
2722892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        try {
2723892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            while (cursor.moveToNext()) {
2724892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                long dataID = cursor.getLong(0);
2725892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                long rawContactID = cursor.getLong(1);
2726892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String number = cursor.getString(2);
2727892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String numberE164 = PhoneNumberUtils.formatNumberToE164(number, mCountryIso);
2728892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String normalizedNumber = PhoneNumberUtils.normalizeNumber(number);
2729892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                if (!TextUtils.isEmpty(normalizedNumber)) {
2730892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.clear();
2731892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactID);
2732892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.DATA_ID, dataID);
2733892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber);
2734892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.MIN_MATCH,
2735892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                            PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber));
2736892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    db.insert(Tables.PHONE_LOOKUP, null, phoneValues);
2737892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2738892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    if (numberE164 != null && !numberE164.equals(normalizedNumber)) {
2739892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, numberE164);
2740892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        phoneValues.put(PhoneLookupColumns.MIN_MATCH,
2741892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                                PhoneNumberUtils.toCallerIDMinMatch(numberE164));
2742892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        db.insert(Tables.PHONE_LOOKUP, null, phoneValues);
2743892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    }
2744892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                }
2745892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
2746892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        } finally {
2747892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            cursor.close();
2748892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
2749892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    }
2750892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
27512530512f639c4979fd7371c7dd25dd67e8118124Bai Tao    private void upgradeToVersion406(SQLiteDatabase db) {
27522530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        db.execSQL("ALTER TABLE calls ADD countryiso TEXT;");
27532530512f639c4979fd7371c7dd25dd67e8118124Bai Tao    }
27542530512f639c4979fd7371c7dd25dd67e8118124Bai Tao
2755d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    private void upgradeToVersion409(SQLiteDatabase db) {
2756d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
2757d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        createDirectoriesTable(db);
2758d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    }
2759d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov
2760385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    /**
2761d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov     * Adding DEFAULT_DIRECTORY table.
2762385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     */
2763d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    private void upgradeToVersion411(SQLiteDatabase db) {
2764d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS " + Tables.DEFAULT_DIRECTORY);
2765385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DEFAULT_DIRECTORY + " (" +
2766385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
2767385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        ");");
2768385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2769385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // Process contacts without an account
2770385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
2771385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " SELECT " + RawContacts.CONTACT_ID +
2772385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS +
2773385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL " +
2774385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL ");
2775385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2776385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // Process accounts that don't have a default group (e.g. Exchange)
2777385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
2778385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " SELECT " + RawContacts.CONTACT_ID +
2779385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS +
2780385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE NOT EXISTS" +
2781385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " (SELECT " + Groups._ID +
2782385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "  FROM " + Tables.GROUPS +
2783385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
2784385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_NAME +
2785385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "    AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
2786385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
2787385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "    AND " + Groups.AUTO_ADD + " != 0" +
2788385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ")");
2789385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2790385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        long mimetype = lookupMimeTypeId(db, GroupMembership.CONTENT_ITEM_TYPE);
2791385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2792d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        // Process accounts that do have a default group (e.g. Google)
2793385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
2794385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " SELECT " + RawContacts.CONTACT_ID +
2795385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS +
2796385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " JOIN " + Tables.DATA +
2797385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "   ON (" + RawContactsColumns.CONCRETE_ID + "=" + Data.RAW_CONTACT_ID + ")" +
2798385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE " + DataColumns.MIMETYPE_ID + "=" + mimetype +
2799d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                " AND EXISTS" +
2800d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                " (SELECT " + Groups._ID +
2801d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "  FROM " + Tables.GROUPS +
2802d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
2803d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_NAME +
2804d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "    AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
2805d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
2806d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "    AND " + Groups.AUTO_ADD + " != 0" +
2807d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                ")");
28083d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
2809385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2810e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    private void upgradeToVersion413(SQLiteDatabase db) {
28113ea7932a47027c8629d3a301e1a16e7d2c8a298dDmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
28123ea7932a47027c8629d3a301e1a16e7d2c8a298dDmitri Plotnikov        createDirectoriesTable(db);
2813e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    }
2814e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov
2815c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov    private void upgradeToVersion415(SQLiteDatabase db) {
2816c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        db.execSQL(
2817c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "ALTER TABLE " + Tables.GROUPS +
2818c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                " ADD " + Groups.GROUP_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0");
2819c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        db.execSQL(
2820c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "UPDATE " + Tables.GROUPS +
2821c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "   SET " + Groups.GROUP_IS_READ_ONLY + "=1" +
2822c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                " WHERE " + Groups.SYSTEM_ID + " NOT NULL");
2823c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov    }
2824c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov
2825b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    public String extractHandleFromEmailAddress(String email) {
2826b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email);
2827b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (tokens.length == 0) {
2828b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return null;
2829b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2830b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2831b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        String address = tokens[0].getAddress();
2832b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        int at = address.indexOf('@');
2833b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (at != -1) {
2834b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return address.substring(0, at);
2835b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2836b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        return null;
2837b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2838b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
283908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov    public String extractAddressFromEmailAddress(String email) {
284008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email);
284108768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        if (tokens.length == 0) {
284208768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            return null;
284308768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        }
284408768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
284508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        return tokens[0].getAddress();
284608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov    }
284708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
2848b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private long lookupMimeTypeId(SQLiteDatabase db, String mimeType) {
2849b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2850b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return DatabaseUtils.longForQuery(db,
2851b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    "SELECT " + MimetypesColumns._ID +
2852b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    " FROM " + Tables.MIMETYPES +
2853b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    " WHERE " + MimetypesColumns.MIMETYPE
2854b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                            + "='" + mimeType + "'", null);
2855b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } catch (SQLiteDoneException e) {
2856b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            // No rows of this type in the database
2857b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return -1;
2858b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2859b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2860b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
28615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void bindString(SQLiteStatement stmt, int index, String value) {
28625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (value == null) {
28635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            stmt.bindNull(index);
28645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } else {
28655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            stmt.bindString(index, value);
28665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
28675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
28685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
286978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private void bindLong(SQLiteStatement stmt, int index, Number value) {
287078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (value == null) {
287178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            stmt.bindNull(index);
287278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        } else {
287378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            stmt.bindLong(index, value.longValue());
287478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
287578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
287678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
2877a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    /**
2878f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * Adds index stats into the SQLite database to force it to always use the lookup indexes.
2879f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     */
2880f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    private void updateSqliteStats(SQLiteDatabase db) {
2881f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2882f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        // Specific stats strings are based on an actual large database after running ANALYZE
2883f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        try {
28848fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.CONTACTS,
28858fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "contacts_restricted_index", "10000 9000");
28868fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.CONTACTS,
28878fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "contacts_has_phone_index", "10000 500");
28888fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
28898fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.RAW_CONTACTS,
28908fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "raw_contacts_source_id_index", "10000 1 1 1");
28918fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.RAW_CONTACTS,
28928fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "raw_contacts_contact_id_index", "10000 2");
28938fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
28948fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
28958fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "name_lookup_raw_contact_id_index", "10000 3");
28968fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
2897916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                    "name_lookup_index", "10000 3 2 2 1");
28988fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
28998fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "sqlite_autoindex_name_lookup_1", "10000 3 2 1");
29008fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
29018fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.PHONE_LOOKUP,
29028fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "phone_lookup_index", "10000 2 2 1");
290336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            updateIndexStats(db, Tables.PHONE_LOOKUP,
290436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    "phone_lookup_min_match_index", "10000 2 2 1");
29058fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
29068fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.DATA,
29078fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "data_mimetype_data1_index", "60000 5000 2");
29088fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.DATA,
29098fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "data_raw_contact_id", "60000 10");
29108fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
29118fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.GROUPS,
29128fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "groups_source_id_index", "50 1 1 1");
29138fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
29148fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NICKNAME_LOOKUP,
29158fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "sqlite_autoindex_name_lookup_1", "500 2 1");
29168fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
2917f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        } catch (SQLException e) {
2918f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            Log.e(TAG, "Could not update index stats", e);
2919f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        }
2920f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2921f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2922f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    /**
2923f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * Stores statistics for a given index.
2924f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     *
2925f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * @param stats has the following structure: the first index is the expected size of
2926f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * the table.  The following integer(s) are the expected number of records selected with the
2927f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * index.  There should be one integer per indexed column.
2928f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     */
29295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void updateIndexStats(SQLiteDatabase db, String table, String index,
29305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String stats) {
2931f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        db.execSQL("DELETE FROM sqlite_stat1 WHERE tbl='" + table + "' AND idx='" + index + "';");
2932f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        db.execSQL("INSERT INTO sqlite_stat1 (tbl,idx,stat)"
2933f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                + " VALUES ('" + table + "','" + index + "','" + stats + "');");
2934f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2935f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2936f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    @Override
2937f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    public synchronized SQLiteDatabase getWritableDatabase() {
2938f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        SQLiteDatabase db = super.getWritableDatabase();
2939f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        if (mReopenDatabase) {
2940f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            mReopenDatabase = false;
2941f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            close();
2942f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            db = super.getWritableDatabase();
2943f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        }
2944f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        return db;
2945f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2946f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2947f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    /**
2948a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov     * Wipes all data except mime type and package lookup tables.
2949a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov     */
2950a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    public void wipeData() {
2951a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
29523d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov
295333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.ACCOUNTS + ";");
295469cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " VALUES(NULL, NULL)");
295533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov
2956d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CONTACTS + ";");
29575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.RAW_CONTACTS + ";");
2958a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.DATA + ";");
2959a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.PHONE_LOOKUP + ";");
2960a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NAME_LOOKUP + ";");
2961ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("DELETE FROM " + Tables.GROUPS + ";");
2962b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.AGGREGATION_EXCEPTIONS + ";");
2963eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        db.execSQL("DELETE FROM " + Tables.SETTINGS + ";");
2964a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.ACTIVITIES + ";");
29653d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CALLS + ";");
296672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.DIRECTORIES + ";");
296772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov
2968b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        // Note: we are not removing reference data from Tables.NICKNAME_LOOKUP
2969a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
2970b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
297104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    public NameSplitter createNameSplitter() {
297204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        return new NameSplitter(
297304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_prefixes),
297404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_last_name_prefixes),
297504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_suffixes),
297604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_conjunctions),
297704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Locale.getDefault());
297804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
297904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
2980b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
2981619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey     * Return the {@link ApplicationInfo#uid} for the given package name.
2982619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey     */
2983619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    public static int getUidForPackageName(PackageManager pm, String packageName) {
2984619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        try {
2985619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            ApplicationInfo clientInfo = pm.getApplicationInfo(packageName, 0 /* no flags */);
2986619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            return clientInfo.uid;
2987619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        } catch (NameNotFoundException e) {
2988619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            throw new RuntimeException(e);
2989619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        }
2990619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
2991619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
2992619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    /**
2993b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Perform an internal string-to-integer lookup using the compiled
2994b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * {@link SQLiteStatement} provided, using the in-memory cache to speed up
2995b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups. If a mapping isn't found in cache or database, it will be
2996b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * created. All new, uncached answers are added to the cache automatically.
2997b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *
2998b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param query Compiled statement used to query for the mapping.
2999b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param insert Compiled statement used to insert a new mapping when no
3000b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *            existing one is found in cache or from query.
3001b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param value Value to find mapping for.
3002b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param cache In-memory cache of previous answers.
3003b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @return An unique integer mapping for the given value.
3004b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3005f4a3b7e523e36679b68edd2af632e26648758ff2Dmitri Plotnikov    private long getCachedId(SQLiteStatement query, SQLiteStatement insert,
3006b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String value, HashMap<String, Long> cache) {
3007b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Try an in-memory cache lookup
3008b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (cache.containsKey(value)) {
3009b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return cache.get(value);
3010b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3011b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3012b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        long id = -1;
3013b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
3014b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try searching database for mapping
3015b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(query, 1, value);
3016b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            id = query.simpleQueryForLong();
3017b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
3018b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Nothing found, so try inserting new mapping
3019b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(insert, 1, value);
3020b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            id = insert.executeInsert();
3021b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3022b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3023b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (id != -1) {
3024b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Cache and return the new answer
3025b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            cache.put(value, id);
3026b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return id;
3027b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } else {
3028b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Otherwise throw if no mapping found or created
3029b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            throw new IllegalStateException("Couldn't find or create internal "
3030b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                    + "lookup table entry for value " + value);
3031b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3032b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3033b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3034b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3035ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Convert a package name into an integer, using {@link Tables#PACKAGES} for
3036b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
3037b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3038b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getPackageId(String packageName) {
303978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mPackageQuery == null) {
304078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mPackageQuery = getWritableDatabase().compileStatement(
304178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + PackagesColumns._ID +
304278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.PACKAGES +
304378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + PackagesColumns.PACKAGE + "=?");
304478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
304578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
304678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mPackageInsert == null) {
304778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mPackageInsert = getWritableDatabase().compileStatement(
304878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT INTO " + Tables.PACKAGES + "("
304978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + PackagesColumns.PACKAGE +
305078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    ") VALUES (?)");
305178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3052b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return getCachedId(mPackageQuery, mPackageInsert, packageName, mPackageCache);
3053b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3054b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3055b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3056ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Convert a mimetype into an integer, using {@link Tables#MIMETYPES} for
3057b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
3058b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3059b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getMimeTypeId(String mimetype) {
3060b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return getCachedId(mMimetypeQuery, mMimetypeInsert, mimetype, mMimetypeCache);
3061b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3062b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
30632a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForStructuredName() {
30642a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdStructuredName;
30652a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
30662a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
30672a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForOrganization() {
30682a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdOrganization;
30692a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
30702a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
30712a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForIm() {
30722a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdIm;
30732a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
30742a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
30752a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForEmail() {
30762a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdEmail;
30772a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
30782a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
30792a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public int getDisplayNameSourceForMimeTypeId(int mimeTypeId) {
30802a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        if (mimeTypeId == mMimeTypeIdStructuredName) {
30812a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.STRUCTURED_NAME;
30822a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdEmail) {
30832a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.EMAIL;
30842a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdPhone) {
30852a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.PHONE;
30862a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdOrganization) {
30872a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.ORGANIZATION;
30882a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdNickname) {
30892a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.NICKNAME;
30902a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else {
30912a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.UNDEFINED;
30922a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        }
30932a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
30942a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
3095b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3096ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Find the mimetype for the given {@link Data#_ID}.
3097b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3098b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getDataMimeType(long dataId) {
309978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mDataMimetypeQuery == null) {
310078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mDataMimetypeQuery = getWritableDatabase().compileStatement(
310178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + MimetypesColumns.MIMETYPE +
310278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.DATA_JOIN_MIMETYPES +
310378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + Tables.DATA + "." + Data._ID + "=?");
310478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3105b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
3106b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
3107b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mDataMimetypeQuery, 1, dataId);
3108b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mDataMimetypeQuery.simpleQueryForString();
3109b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
3110b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
3111b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
3112b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
3113b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3114b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3115b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3116b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3117b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Find the mime-type for the given {@link Activities#_ID}.
3118b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3119b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getActivityMimeType(long activityId) {
312078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mActivitiesMimetypeQuery == null) {
312178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mActivitiesMimetypeQuery = getWritableDatabase().compileStatement(
312278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + MimetypesColumns.MIMETYPE +
312378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.ACTIVITIES_JOIN_MIMETYPES +
312478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + Tables.ACTIVITIES + "." + Activities._ID + "=?");
312578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3126b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
3127b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
3128b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mActivitiesMimetypeQuery, 1, activityId);
3129b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mActivitiesMimetypeQuery.simpleQueryForString();
3130b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
3131b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
3132b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
3133b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
3134b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3135b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
31366bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov
31376bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov    /**
3138d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Update {@link Contacts#IN_VISIBLE_GROUP} for all contacts.
3139ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     */
3140ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public void updateAllVisible() {
3141385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        updateCustomContactVisibility(getWritableDatabase(), "");
3142ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
3143ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
3144ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    /**
3145385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     * Update {@link Contacts#IN_VISIBLE_GROUP} and
3146385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     * {@link Tables#DEFAULT_DIRECTORY} for a specific contact.
3147ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     */
3148fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov    public void updateContactVisible(long contactId) {
31494394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
3150385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        updateCustomContactVisibility(getWritableDatabase(),
3151385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " AND " + Contacts._ID + "=" + contactId);
3152385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3153385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        String contactIdAsString = String.valueOf(contactId);
3154385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        long mimetype = getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
3155385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3156385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // The contact will be included in the default directory if contains
3157d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        // a raw contact that is in any group or in an account that
3158385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // does not have any AUTO_ADD groups.
3159385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        long visibleRawContact = DatabaseUtils.longForQuery(db,
3160385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "SELECT EXISTS (" +
3161385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts.CONTACT_ID +
3162385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3163385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " JOIN " + Tables.DATA +
3164385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   ON (" + RawContactsColumns.CONCRETE_ID + "="
3165385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                            + Data.RAW_CONTACT_ID + ")" +
3166385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3167385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + DataColumns.MIMETYPE_ID + "=?" +
3168385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ") OR EXISTS (" +
3169385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts._ID +
3170385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3171385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3172385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND NOT EXISTS" +
3173385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        " (SELECT " + Groups._ID +
3174385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  FROM " + Tables.GROUPS +
3175385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
3176385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                                + GroupsColumns.CONCRETE_ACCOUNT_NAME +
3177385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
3178385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                                + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
3179385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  AND " + Groups.AUTO_ADD + " != 0" +
3180385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        ")" +
3181385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ") OR EXISTS (" +
3182385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts._ID +
3183385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3184385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3185385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL " +
3186385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL" +
3187385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ")",
3188385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                new String[] {
3189385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    contactIdAsString,
31906c47e208236a62c55f396116e087331e05e148f3Dmitri Plotnikov                    String.valueOf(mimetype),
3191385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    contactIdAsString,
31926c47e208236a62c55f396116e087331e05e148f3Dmitri Plotnikov                    contactIdAsString
3193385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                });
3194385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3195385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        if (visibleRawContact != 0) {
3196385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY + " VALUES(?)",
3197385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    new String[] { contactIdAsString });
3198385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        } else {
3199385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            db.execSQL("DELETE FROM " + Tables.DEFAULT_DIRECTORY + " WHERE " + Contacts._ID + "=?",
3200385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    new String[] { contactIdAsString });
3201385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        }
3202385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    }
32034394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
3204385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    private void updateCustomContactVisibility(SQLiteDatabase db, String selection) {
3205ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        final long groupMembershipMimetypeId = getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
32064394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        String[] selectionArgs = new String[]{String.valueOf(groupMembershipMimetypeId)};
32074394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
32084394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // First delete what needs to be deleted, then insert what needs to be added.
32094394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // Since flash writes are very expensive, this approach is much better than
32104394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // delete-all-insert-all.
32114394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.VISIBLE_CONTACTS +
32124394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " WHERE " + "_id NOT IN" +
32134394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        "(SELECT " + Contacts._ID +
32144394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        " FROM " + Tables.CONTACTS +
32154394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        " WHERE (" + Clauses.CONTACT_IS_VISIBLE + ")=1) " + selection,
32164394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                selectionArgs);
3217fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
32184394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.VISIBLE_CONTACTS +
32194394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " SELECT " + Contacts._ID +
32204394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " FROM " + Tables.CONTACTS +
32214394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " WHERE " + Contacts._ID +
32224394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " NOT IN " + Tables.VISIBLE_CONTACTS +
32234394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                           " AND (" + Clauses.CONTACT_IS_VISIBLE + ")=1 " + selection,
32244394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                selectionArgs);
3225ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
3226ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
3227ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    /**
3228d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Returns contact ID for the given contact or zero if it is NULL.
32296bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov     */
3230d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    public long getContactId(long rawContactId) {
323178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mContactIdQuery == null) {
323278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mContactIdQuery = getWritableDatabase().compileStatement(
323378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + RawContacts.CONTACT_ID +
323478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
323578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts._ID + "=?");
323678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
32376bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        try {
3238d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov            DatabaseUtils.bindObjectToProgram(mContactIdQuery, 1, rawContactId);
3239d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov            return mContactIdQuery.simpleQueryForLong();
32406bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        } catch (SQLiteDoneException e) {
3241a3bd0246ca3741877488bca7aadd91c79b2fd8d2Fred Quintana            // No valid mapping found, so return 0
32426bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov            return 0;
32436bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        }
32446bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov    }
324561bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov
32465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov    public int getAggregationMode(long rawContactId) {
324778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mAggregationModeQuery == null) {
324878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mAggregationModeQuery = getWritableDatabase().compileStatement(
324978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + RawContacts.AGGREGATION_MODE +
325078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
325178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts._ID + "=?");
325278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3253f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        try {
32545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov            DatabaseUtils.bindObjectToProgram(mAggregationModeQuery, 1, rawContactId);
3255f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            return (int)mAggregationModeQuery.simpleQueryForLong();
3256f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        } catch (SQLiteDoneException e) {
32576cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov            // No valid row found, so return "disabled"
32586cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov            return RawContacts.AGGREGATION_MODE_DISABLED;
3259f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3260f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3261f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
3262892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    public void buildPhoneLookupAndContactQuery(
3263892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            SQLiteQueryBuilder qb, String normalizedNumber, String numberE164) {
3264892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        String minMatch = PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber);
3265e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        StringBuilder sb = new StringBuilder();
326636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        appendPhoneLookupTables(sb, minMatch, true);
3267e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        qb.setTables(sb.toString());
3268e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
3269e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb = new StringBuilder();
3270892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        appendPhoneLookupSelection(sb, normalizedNumber, numberE164);
3271e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        qb.appendWhere(sb.toString());
3272bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    }
3273bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
3274e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    public String buildPhoneLookupAsNestedQuery(String number) {
3275e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        StringBuilder sb = new StringBuilder();
327636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        final String minMatch = PhoneNumberUtils.toCallerIDMinMatch(number);
3277e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append("(SELECT DISTINCT raw_contact_id" + " FROM ");
327836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        appendPhoneLookupTables(sb, minMatch, false);
3279e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(" WHERE ");
3280892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        appendPhoneLookupSelection(sb, number, null);
3281e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(")");
3282e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        return sb.toString();
3283e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    }
3284e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
328536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    private void appendPhoneLookupTables(StringBuilder sb, final String minMatch,
3286e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov            boolean joinContacts) {
3287e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(Tables.RAW_CONTACTS);
3288e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        if (joinContacts) {
3289fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov            sb.append(" JOIN " + getContactView() + " contacts_view"
3290fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                    + " ON (contacts_view._id = raw_contacts.contact_id)");
3291e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        }
3292892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        sb.append(", (SELECT data_id, normalized_number, length(normalized_number) as len "
3293892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " FROM phone_lookup " + " WHERE (" + Tables.PHONE_LOOKUP + "."
3294892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + PhoneLookupColumns.MIN_MATCH + " = '");
329536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        sb.append(minMatch);
329636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        sb.append("')) AS lookup, " + Tables.DATA);
3297e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    }
3298e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
3299892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    private void appendPhoneLookupSelection(StringBuilder sb, String number, String numberE164) {
3300892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        sb.append("lookup.data_id=data._id AND data.raw_contact_id=raw_contacts._id");
3301892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        boolean hasNumberE164 = !TextUtils.isEmpty(numberE164);
3302892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        boolean hasNumber = !TextUtils.isEmpty(number);
3303892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (hasNumberE164 || hasNumber) {
3304892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            sb.append(" AND ( ");
3305892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumberE164) {
3306892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" lookup.normalized_number = ");
3307892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                DatabaseUtils.appendEscapedSQLString(sb, numberE164);
3308892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3309892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumberE164 && hasNumber) {
3310892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" OR ");
3311892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3312892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumber) {
3313892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                int numberLen = number.length();
3314892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" lookup.len <= ");
3315892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(numberLen);
3316892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" AND substr(");
3317892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                DatabaseUtils.appendEscapedSQLString(sb, number);
3318892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(',');
3319892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(numberLen);
3320892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" - lookup.len + 1) = lookup.normalized_number");
3321892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3322892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            sb.append(')');
3323892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
332436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    }
332536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
332636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    public String getUseStrictPhoneNumberComparisonParameter() {
332736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        return mUseStrictPhoneNumberComparison ? "1" : "0";
3328fb362d1a5df250a49fad06db323b0d41fe0e3757Dmitri Plotnikov    }
3329bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
3330619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    /**
3331b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     * Loads common nickname mappings into the database.
3332b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     */
3333b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private void loadNicknameLookupTable(SQLiteDatabase db) {
333451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NICKNAME_LOOKUP);
333551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
333628f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar        String[] strings = mContext.getResources().getStringArray(
333728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar                com.android.internal.R.array.common_nicknames);
3338b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        if (strings == null || strings.length == 0) {
3339b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            return;
3340b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
3341b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
3342b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        SQLiteStatement nicknameLookupInsert = db.compileStatement("INSERT INTO "
3343b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                + Tables.NICKNAME_LOOKUP + "(" + NicknameLookupColumns.NAME + ","
3344b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                + NicknameLookupColumns.CLUSTER + ") VALUES (?,?)");
3345b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
334651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
334751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            for (int clusterId = 0; clusterId < strings.length; clusterId++) {
334851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                String[] names = strings[clusterId].split(",");
334951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                for (int j = 0; j < names.length; j++) {
335051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    String name = NameNormalizer.normalize(names[j]);
335151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    try {
335251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        DatabaseUtils.bindObjectToProgram(nicknameLookupInsert, 1, name);
335351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        DatabaseUtils.bindObjectToProgram(nicknameLookupInsert, 2,
335451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                                String.valueOf(clusterId));
335551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        nicknameLookupInsert.executeInsert();
335651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    } catch (SQLiteException e) {
335751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
335851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        // Print the exception and keep going - this is not a fatal error
335951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        Log.e(TAG, "Cannot insert nickname: " + names[j], e);
336051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    }
3361b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                }
3362b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            }
336351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
336451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            nicknameLookupInsert.close();
3365b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
3366b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    }
3367b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
3368f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    public static void copyStringValue(ContentValues toValues, String toKey,
3369f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            ContentValues fromValues, String fromKey) {
3370f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        if (fromValues.containsKey(fromKey)) {
3371f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            toValues.put(toKey, fromValues.getAsString(fromKey));
3372f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3373f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3374f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
3375f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    public static void copyLongValue(ContentValues toValues, String toKey,
3376f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            ContentValues fromValues, String fromKey) {
3377f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        if (fromValues.containsKey(fromKey)) {
3378f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            long longValue;
3379f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            Object value = fromValues.get(fromKey);
3380f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            if (value instanceof Boolean) {
3381f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                if ((Boolean)value) {
3382f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                    longValue = 1;
3383f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                } else {
3384f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                    longValue = 0;
3385f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                }
33861b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov            } else if (value instanceof String) {
33871b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov                longValue = Long.parseLong((String)value);
3388f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            } else {
33891b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov                longValue = ((Number)value).longValue();
3390f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            }
3391f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            toValues.put(toKey, longValue);
3392f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3393f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3394f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
339535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    public SyncStateContentProviderHelper getSyncState() {
339635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        return mSyncState;
339735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    }
3398c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3399c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    /**
3400c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     * Delete the aggregate contact if it has no constituent raw contacts other
3401c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     * than the supplied one.
3402c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     */
3403c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    public void removeContactIfSingleton(long rawContactId) {
3404c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
3405c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3406c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        // Obtain contact ID from the supplied raw contact ID
3407c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        String contactIdFromRawContactId = "(SELECT " + RawContacts.CONTACT_ID + " FROM "
3408c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=" + rawContactId + ")";
3409c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3410c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        // Find other raw contacts in the same aggregate contact
3411c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        String otherRawContacts = "(SELECT contacts1." + RawContacts._ID + " FROM "
3412c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + Tables.RAW_CONTACTS + " contacts1 JOIN " + Tables.RAW_CONTACTS + " contacts2 ON ("
3413c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "contacts1." + RawContacts.CONTACT_ID + "=contacts2." + RawContacts.CONTACT_ID
3414c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + ") WHERE contacts1." + RawContacts._ID + "!=" + rawContactId + ""
3415c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " AND contacts2." + RawContacts._ID + "=" + rawContactId + ")";
3416c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3417c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CONTACTS
3418c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " WHERE " + Contacts._ID + "=" + contactIdFromRawContactId
3419c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " AND NOT EXISTS " + otherRawContacts + ";");
3420c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    }
34214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
34224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    /**
3423b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     * Returns the value from the {@link Tables#PROPERTIES} table.
3424b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     */
3425b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public String getProperty(String key, String defaultValue) {
3426b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        Cursor cursor = getReadableDatabase().query(Tables.PROPERTIES,
3427b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                new String[]{PropertiesColumns.PROPERTY_VALUE},
3428b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_KEY + "=?",
3429b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                new String[]{key}, null, null, null);
3430b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        String value = null;
3431b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        try {
3432b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            if (cursor.moveToFirst()) {
3433b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                value = cursor.getString(0);
3434b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            }
3435b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        } finally {
3436b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            cursor.close();
3437b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        }
3438b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3439b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        return value != null ? value : defaultValue;
3440b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
3441b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3442b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    /**
3443b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     * Stores a key-value pair in the {@link Tables#PROPERTIES} table.
3444b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     */
3445b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public void setProperty(String key, String value) {
34463d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        setProperty(getWritableDatabase(), key, value);
34473d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
34483d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
34493d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    private void setProperty(SQLiteDatabase db, String key, String value) {
3450b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ContentValues values = new ContentValues();
3451b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        values.put(PropertiesColumns.PROPERTY_KEY, key);
3452b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        values.put(PropertiesColumns.PROPERTY_VALUE, value);
34533d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        db.replace(Tables.PROPERTIES, null, values);
3454b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
3455b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3456b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    /**
34574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     * Check if {@link Binder#getCallingUid()} should be allowed access to
34584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     * {@link RawContacts#IS_RESTRICTED} data.
34594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     */
3460d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    boolean hasAccessToRestrictedData() {
34614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        final PackageManager pm = mContext.getPackageManager();
34626ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        int caller = Binder.getCallingUid();
34636ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        if (caller == 0) return true; // root can do anything
34646ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        final String[] callerPackages = pm.getPackagesForUid(caller);
34654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
34664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        // Has restricted access if caller matches any packages
34674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        for (String callerPackage : callerPackages) {
3468d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton            if (hasAccessToRestrictedData(callerPackage)) {
3469763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                return true;
3470763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar            }
3471763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        }
3472763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return false;
3473763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    }
3474763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar
3475763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    /**
3476763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     * Check if requestingPackage should be allowed access to
3477763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     * {@link RawContacts#IS_RESTRICTED} data.
3478763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     */
3479d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    boolean hasAccessToRestrictedData(String requestingPackage) {
3480d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        if (mUnrestrictedPackages != null) {
3481d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton            for (String allowedPackage : mUnrestrictedPackages) {
3482d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                if (allowedPackage.equals(requestingPackage)) {
3483d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                    return true;
3484d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                }
34854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov            }
34864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        }
34874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        return false;
34884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
34894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
34904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getDataView() {
3491d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa        return getDataView(false);
3492d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3493d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3494d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    public String getDataView(boolean requireRestrictedView) {
3495d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3496d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa                Views.DATA_ALL : Views.DATA_RESTRICTED;
34974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
34984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
34994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getRawContactView() {
3500763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return getRawContactView(false);
3501763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    }
3502763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar
3503763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    public String getRawContactView(boolean requireRestrictedView) {
3504d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3505763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                Views.RAW_CONTACTS_ALL : Views.RAW_CONTACTS_RESTRICTED;
35064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
35074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
35084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getContactView() {
3509763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return getContactView(false);
35104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
35114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
3512763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    public String getContactView(boolean requireRestrictedView) {
3513d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3514763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                Views.CONTACTS_ALL : Views.CONTACTS_RESTRICTED;
3515f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey    }
3516f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey
351789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov    public String getGroupView() {
351889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        return Views.GROUPS_ALL;
351989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov    }
352089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
3521a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getRawEntitiesView() {
3522a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return getRawEntitiesView(false);
3523a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    }
3524a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
3525a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getRawEntitiesView(boolean requireRestrictedView) {
3526a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3527a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                Views.RAW_ENTITIES : Views.RAW_ENTITIES_RESTRICTED;
3528a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    }
3529a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
3530a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getEntitiesView() {
3531a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return getEntitiesView(false);
3532d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3533d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3534a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getEntitiesView(boolean requireRestrictedView) {
3535d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3536a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                Views.ENTITIES : Views.ENTITIES_RESTRICTED;
3537d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3538d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3539ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov    /**
3540ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov     * Test if any of the columns appear in the given projection.
3541ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov     */
3542ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov    public boolean isInProjection(String[] projection, String... columns) {
354382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        if (projection == null) {
354482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            return true;
354582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        }
3546ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov
354782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        // Optimized for a single-column test
354882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        if (columns.length == 1) {
354982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            String column = columns[0];
355082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            for (String test : projection) {
355182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                if (column.equals(test)) {
355282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                    return true;
355382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                }
355482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            }
355582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        } else {
355682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            for (String test : projection) {
355782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                for (String column : columns) {
3558ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                    if (column.equals(test)) {
3559ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                        return true;
3560ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                    }
3561ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                }
3562ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov            }
3563ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov        }
3564ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov        return false;
35654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
3566fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3567fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    /**
3568fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * Returns a detailed exception message for the supplied URI.  It includes the calling
3569fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * user and calling package(s).
3570fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     */
3571fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    public String exceptionMessage(Uri uri) {
3572fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        return exceptionMessage(null, uri);
3573fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    }
3574fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3575fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    /**
3576fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * Returns a detailed exception message for the supplied URI.  It includes the calling
3577fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * user and calling package(s).
3578fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     */
3579fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    public String exceptionMessage(String message, Uri uri) {
3580fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        StringBuilder sb = new StringBuilder();
3581fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (message != null) {
3582fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(message).append("; ");
3583fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3584fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        sb.append("URI: ").append(uri);
3585fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        final PackageManager pm = mContext.getPackageManager();
3586fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        int callingUid = Binder.getCallingUid();
3587fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        sb.append(", calling user: ");
3588fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        String userName = pm.getNameForUid(callingUid);
3589fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (userName != null) {
3590fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(userName);
3591fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        } else {
3592fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(callingUid);
3593fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3594fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3595fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        final String[] callerPackages = pm.getPackagesForUid(callingUid);
3596fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (callerPackages != null && callerPackages.length > 0) {
3597fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            if (callerPackages.length == 1) {
3598fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(", calling package:");
3599fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(callerPackages[0]);
3600fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            } else {
3601fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(", calling package is one of: [");
3602fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                for (int i = 0; i < callerPackages.length; i++) {
3603fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    if (i != 0) {
3604fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                        sb.append(", ");
3605fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    }
3606fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    sb.append(callerPackages[i]);
3607fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                }
3608fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append("]");
3609fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            }
3610fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3611fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3612fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        return sb.toString();
3613fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    }
3614892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
3615892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    protected String getCountryIso() {
3616892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        CountryDetector detector =
3617892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            (CountryDetector) mContext.getSystemService(Context.COUNTRY_DETECTOR);
3618892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        return detector.detectCountry().getCountryIso();
3619892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    }
362078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
362178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void deleteStatusUpdate(long dataId) {
362278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mStatusUpdateDelete == null) {
362378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateDelete = getWritableDatabase().compileStatement(
362478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "DELETE FROM " + Tables.STATUS_UPDATES +
362578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + StatusUpdatesColumns.DATA_ID + "=?");
362678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
362778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateDelete.bindLong(1, dataId);
362878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateDelete.execute();
362978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
363078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
363178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void replaceStatusUpdate(Long dataId, long timestamp, String status, String resPackage,
363278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            Long iconResource, Integer labelResource) {
363378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mStatusUpdateReplace == null) {
363478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateReplace = getWritableDatabase().compileStatement(
363578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "("
363678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdatesColumns.DATA_ID + ", "
363778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_TIMESTAMP + ","
363878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS + ","
363978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_RES_PACKAGE + ","
364078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_ICON + ","
364178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_LABEL + ")" +
364278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " VALUES (?,?,?,?,?,?)");
364378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
364478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace.bindLong(1, dataId);
364578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace.bindLong(2, timestamp);
364678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mStatusUpdateReplace, 3, status);
364778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mStatusUpdateReplace, 4, resPackage);
364878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindLong(mStatusUpdateReplace, 5, iconResource);
364978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindLong(mStatusUpdateReplace, 6, labelResource);
365078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace.execute();
365178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
365278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
365378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void insertStatusUpdate(Long dataId, String status, String resPackage, Long iconResource,
365478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            Integer labelResource) {
365578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mStatusUpdateInsert == null) {
365678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateInsert = getWritableDatabase().compileStatement(
365778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT INTO " + Tables.STATUS_UPDATES + "("
365878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdatesColumns.DATA_ID + ", "
365978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS + ","
366078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_RES_PACKAGE + ","
366178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_ICON + ","
366278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_LABEL + ")" +
366378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " VALUES (?,?,?,?,?)");
366478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
366578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        try {
366678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateInsert.bindLong(1, dataId);
366778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateInsert, 2, status);
366878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateInsert, 3, resPackage);
366978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusUpdateInsert, 4, iconResource);
367078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusUpdateInsert, 5, labelResource);
367178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateInsert.executeInsert();
367278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        } catch (SQLiteConstraintException e) {
367378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            // The row already exists - update it
367478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            if (mStatusUpdateAutoTimestamp == null) {
367578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                mStatusUpdateAutoTimestamp = getWritableDatabase().compileStatement(
367678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        "UPDATE " + Tables.STATUS_UPDATES +
367778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?,"
367878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + StatusUpdates.STATUS + "=?" +
367978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"
368078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + " AND " + StatusUpdates.STATUS + "!=?");
368178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            }
368278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
368378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            long timestamp = System.currentTimeMillis();
368478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateAutoTimestamp.bindLong(1, timestamp);
368578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateAutoTimestamp, 2, status);
368678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateAutoTimestamp.bindLong(3, dataId);
368778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateAutoTimestamp, 4, status);
368878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateAutoTimestamp.execute();
368978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
369078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            if (mStatusAttributionUpdate == null) {
369178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                mStatusAttributionUpdate = getWritableDatabase().compileStatement(
369278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        "UPDATE " + Tables.STATUS_UPDATES +
369378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?,"
369478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + StatusUpdates.STATUS_ICON + "=?,"
369578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + StatusUpdates.STATUS_LABEL + "=?" +
369678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " WHERE " + StatusUpdatesColumns.DATA_ID + "=?");
369778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            }
369878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusAttributionUpdate, 1, resPackage);
369978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusAttributionUpdate, 2, iconResource);
370078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusAttributionUpdate, 3, labelResource);
370178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusAttributionUpdate.bindLong(4, dataId);
370278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusAttributionUpdate.execute();
370378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
370478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
370578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
370678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /**
370778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Resets the {@link RawContacts#NAME_VERIFIED} flag to 0 on all other raw
370878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * contacts in the same aggregate
370978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
371078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void resetNameVerifiedForOtherRawContacts(long rawContactId) {
371178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mResetNameVerifiedForOtherRawContacts == null) {
371278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mResetNameVerifiedForOtherRawContacts = getWritableDatabase().compileStatement(
371378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.RAW_CONTACTS +
371478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + RawContacts.NAME_VERIFIED + "=0" +
371578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=(" +
371678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            "SELECT " + RawContacts.CONTACT_ID +
371778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " FROM " + Tables.RAW_CONTACTS +
371878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " WHERE " + RawContacts._ID + "=?)" +
371978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " AND " + RawContacts._ID + "!=?");
372078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
372178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts.bindLong(1, rawContactId);
372278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts.bindLong(2, rawContactId);
372378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts.execute();
372478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
372578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
372678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void setDisplayName(long rawContactId, int displayNameSource,
372778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            String displayNamePrimary, String displayNameAlternative, String phoneticName,
372878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            int phoneticNameStyle, String sortKeyPrimary, String sortKeyAlternative) {
372978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mRawContactDisplayNameUpdate == null) {
373078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mRawContactDisplayNameUpdate = getWritableDatabase().compileStatement(
373178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.RAW_CONTACTS +
373278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " +
373378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.DISPLAY_NAME_SOURCE + "=?," +
373478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.DISPLAY_NAME_PRIMARY + "=?," +
373578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," +
373678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.PHONETIC_NAME + "=?," +
373778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.PHONETIC_NAME_STYLE + "=?," +
373878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.SORT_KEY_PRIMARY + "=?," +
373978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.SORT_KEY_ALTERNATIVE + "=?" +
374078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts._ID + "=?");
374178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
374278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate.bindLong(1, displayNameSource);
374378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 2, displayNamePrimary);
374478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 3, displayNameAlternative);
374578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 4, phoneticName);
374678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate.bindLong(5, phoneticNameStyle);
374778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 6, sortKeyPrimary);
374878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 7, sortKeyAlternative);
374978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate.bindLong(8, rawContactId);
375078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate.execute();
375178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
375278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
375378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /*
375478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Sets the given dataId record in the "data" table to primary, and resets all data records of
375578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * the same mimetype and under the same contact to not be primary.
375678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     *
375778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * @param dataId the id of the data record to be set to primary. Pass -1 to clear the primary
375878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * flag of all data items of this raw contacts
375978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
376078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) {
376178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mSetPrimaryStatement == null) {
376278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mSetPrimaryStatement = getWritableDatabase().compileStatement(
376378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.DATA +
376478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + Data.IS_PRIMARY + "=(_id=?)" +
376578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=?" +
376678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "   AND " + Data.RAW_CONTACT_ID + "=?");
376778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
376878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.bindLong(1, dataId);
376978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.bindLong(2, mimeTypeId);
377078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.bindLong(3, rawContactId);
377178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.execute();
377278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
377378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
377478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /*
377578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Clears the super primary of all data items of the given raw contact. does not touch
377678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * other raw contacts of the same joined aggregate
377778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
377878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void clearSuperPrimary(long rawContactId, long mimeTypeId) {
377978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mClearSuperPrimaryStatement == null) {
378078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mClearSuperPrimaryStatement = getWritableDatabase().compileStatement(
378178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.DATA +
378278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + Data.IS_SUPER_PRIMARY + "=0" +
378378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=?" +
378478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "   AND " + Data.RAW_CONTACT_ID + "=?");
378578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
378678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement.bindLong(1, mimeTypeId);
378778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement.bindLong(2, rawContactId);
378878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement.execute();
378978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
379078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
379178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /*
379278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Sets the given dataId record in the "data" table to "super primary", and resets all data
379378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * records of the same mimetype and under the same aggregate to not be "super primary".
379478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     *
379578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * @param dataId the id of the data record to be set to primary.
379678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
379778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) {
379878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mSetSuperPrimaryStatement == null) {
379978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mSetSuperPrimaryStatement = getWritableDatabase().compileStatement(
380078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.DATA +
380178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" +
380278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=?" +
380378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "   AND " + Data.RAW_CONTACT_ID + " IN (" +
380478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            "SELECT " + RawContacts._ID +
380578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " FROM " + Tables.RAW_CONTACTS +
380678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " WHERE " + RawContacts.CONTACT_ID + " =(" +
380778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                    "SELECT " + RawContacts.CONTACT_ID +
380878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                    " FROM " + Tables.RAW_CONTACTS +
380978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                    " WHERE " + RawContacts._ID + "=?))");
381078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
381178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.bindLong(1, dataId);
381278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.bindLong(2, mimeTypeId);
381378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.bindLong(3, rawContactId);
381478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.execute();
381578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
381678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
381778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /**
381878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Inserts a record in the {@link Tables#NAME_LOOKUP} table.
381978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
382078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) {
382178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (TextUtils.isEmpty(name)) {
382278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            return;
382378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
382478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
382578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mNameLookupInsert == null) {
382678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mNameLookupInsert = getWritableDatabase().compileStatement(
382778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "("
382878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.RAW_CONTACT_ID + ","
382978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.DATA_ID + ","
383078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.NAME_TYPE + ","
383178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.NORMALIZED_NAME
383278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    + ") VALUES (?,?,?,?)");
383378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
383478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.bindLong(1, rawContactId);
383578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.bindLong(2, dataId);
383678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.bindLong(3, lookupType);
383778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mNameLookupInsert, 4, name);
383878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.executeInsert();
383978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
384078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
384178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /**
384278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element.
384378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
384478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void deleteNameLookup(long dataId) {
384578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mNameLookupDelete == null) {
384678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mNameLookupDelete = getWritableDatabase().compileStatement(
384778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "DELETE FROM " + Tables.NAME_LOOKUP +
384878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + NameLookupColumns.DATA_ID + "=?");
384978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
385078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupDelete.bindLong(1, dataId);
385178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupDelete.execute();
385278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
3853189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov
3854e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public void insertNameLookupForOrganization(long rawContactId, long dataId, String company,
3855e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            String title) {
3856e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (!TextUtils.isEmpty(company)) {
3857e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            insertNameLookup(rawContactId, dataId,
3858e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov                    NameLookupType.ORGANIZATION, NameNormalizer.normalize(company));
3859e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3860e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (!TextUtils.isEmpty(title)) {
3861e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            insertNameLookup(rawContactId, dataId,
3862e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov                    NameLookupType.ORGANIZATION, NameNormalizer.normalize(title));
3863e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3864e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
3865e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3866e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public String insertNameLookupForEmail(long rawContactId, long dataId, String email) {
3867e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (TextUtils.isEmpty(email)) {
3868e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            return null;
3869e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3870e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3871e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        String address = extractHandleFromEmailAddress(email);
3872e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (address == null) {
3873e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            return null;
3874e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3875e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3876e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        insertNameLookup(rawContactId, dataId,
3877e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov                NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address));
3878e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        return address;
3879e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
3880e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3881e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    /**
3882e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov     * Normalizes the nickname and inserts it in the name lookup table.
3883e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov     */
3884e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) {
3885e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (TextUtils.isEmpty(nickname)) {
3886e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            return;
3887e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3888e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3889e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        insertNameLookup(rawContactId, dataId,
3890e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov                NameLookupType.NICKNAME, NameNormalizer.normalize(nickname));
3891e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
3892e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
38935df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov    public void insertNameLookupForPhoneticName(long rawContactId, long dataId, String familyName,
38945df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            String middleName, String givenName) {
38955df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        mSb.setLength(0);
38965df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (familyName != null) {
38975df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            mSb.append(familyName.trim());
38985df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
38995df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (middleName != null) {
39005df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            mSb.append(middleName.trim());
39015df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
39025df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (givenName != null) {
39035df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            mSb.append(givenName.trim());
39045df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
39055df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov
39065df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (mSb.length() > 0) {
39075df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            insertNameLookup(rawContactId, dataId, NameLookupType.NAME_COLLATION_KEY,
39085df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov                    NameNormalizer.normalize(mSb.toString()));
39095df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
39105df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov
39115df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (givenName != null) {
39125df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            // We want the phonetic given name to be used for search, but not for aggregation,
39135df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            // which is why we are using NAME_SHORTHAND rather than NAME_COLLATION_KEY
39145df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            insertNameLookup(rawContactId, dataId, NameLookupType.NAME_SHORTHAND,
39155df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov                    NameNormalizer.normalize(givenName.trim()));
39165df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
39175df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov    }
39185df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov
3919189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov    /**
3920189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov     * Performs a query and returns true if any Data item of the raw contact with the given
3921189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov     * id and mimetype is marked as super-primary
3922189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov     */
3923189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov    public boolean rawContactHasSuperPrimary(long rawContactId, long mimeTypeId) {
3924189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        final Cursor existsCursor = getReadableDatabase().rawQuery(
3925189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                "SELECT EXISTS(SELECT 1 FROM " + Tables.DATA +
3926189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                " WHERE " + Data.RAW_CONTACT_ID + "=?" +
3927189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                " AND " + DataColumns.MIMETYPE_ID + "=?" +
3928189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                " AND " + Data.IS_SUPER_PRIMARY + "<>0)",
3929189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                new String[] { String.valueOf(rawContactId), String.valueOf(mimeTypeId) });
3930189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        try {
3931189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov            if (!existsCursor.moveToFirst()) throw new IllegalStateException();
3932189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov            return existsCursor.getInt(0) != 0;
3933189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        } finally {
3934189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov            existsCursor.close();
3935189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        }
3936189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov    }
3937e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3938e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public String getCurrentCountryIso() {
3939e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        return mCountryMonitor.getCountryIso();
3940e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
3941b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey}
3942