ContactsDatabaseHelper.java revision 50a7c86b4b49870bd19d5270722be3f1fccaf226
1b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey/*
2b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Copyright (C) 2009 The Android Open Source Project
3b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
4b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * you may not use this file except in compliance with the License.
6b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * You may obtain a copy of the License at
7b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
8b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
10b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Unless required by applicable law or agreed to in writing, software
11b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * See the License for the specific language governing permissions and
14b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * limitations under the License
15b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey */
16b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarpackage com.android.providers.contacts;
18b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1953214b3ed12b0ff9cb589b6559311f2ac142f2e3Bjorn Bringertimport com.android.common.content.SyncStateContentProviderHelper;
2067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
2182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.content.ContentResolver;
22619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.ContentValues;
23b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.content.Context;
24619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.ApplicationInfo;
25619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.PackageManager;
26619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
27d91272b48f97243533c6580981e12a4847b5783fJeff Hamiltonimport android.content.res.Resources;
2836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikovimport android.database.Cursor;
29b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.DatabaseUtils;
30f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikovimport android.database.SQLException;
3178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException;
32b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteDatabase;
33b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteDoneException;
34b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikovimport android.database.sqlite.SQLiteException;
35b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteOpenHelper;
36bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikovimport android.database.sqlite.SQLiteQueryBuilder;
37b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteStatement;
38892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikovimport android.location.CountryDetector;
39fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikovimport android.net.Uri;
404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikovimport android.os.Binder;
41a3bd0246ca3741877488bca7aadd91c79b2fd8d2Fred Quintanaimport android.os.Bundle;
42c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamiltonimport android.os.SystemClock;
43b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.provider.BaseColumns;
44e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.provider.CallLog.Calls;
45a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract;
46b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions;
47a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email;
48a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.GroupMembership;
492a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im;
50a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname;
51a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization;
52a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone;
53a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.SipAddress;
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     */
948d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov    static final int DATABASE_VERSION = 417;
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;
493a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov    private long mMimeTypeIdSip;
4942a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdStructuredName;
4952a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdOrganization;
4962a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdNickname;
4972a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdPhone;
498b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
499b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** Compiled statements for querying and inserting mappings */
500b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mMimetypeQuery;
501b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mPackageQuery;
502d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    private SQLiteStatement mContactIdQuery;
503f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    private SQLiteStatement mAggregationModeQuery;
504b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mMimetypeInsert;
505b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mPackageInsert;
506b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mDataMimetypeQuery;
507b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mActivitiesMimetypeQuery;
508b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
50978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for setting a data record to the primary. */
51078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mSetPrimaryStatement;
51178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for setting a data record to the super primary. */
51278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mSetSuperPrimaryStatement;
51378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for clearing super primary of a single record. */
51478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mClearSuperPrimaryStatement;
51578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for updating a contact display name */
51678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mRawContactDisplayNameUpdate;
51778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
51878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mNameLookupInsert;
51978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mNameLookupDelete;
52078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateAutoTimestamp;
52178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateInsert;
52278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateReplace;
52378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusAttributionUpdate;
52478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateDelete;
52578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mResetNameVerifiedForOtherRawContacts;
526f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    private SQLiteStatement mContactInDefaultDirectoryQuery;
52778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
528b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private final Context mContext;
5292a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private final boolean mDatabaseOptimizationEnabled;
53035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    private final SyncStateContentProviderHelper mSyncState;
531e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    private final CountryMonitor mCountryMonitor;
5325df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov    private StringBuilder mSb = new StringBuilder();
533f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov
534f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    private boolean mReopenDatabase = false;
535f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
536b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    private static ContactsDatabaseHelper sSingleton = null;
537b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
53836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    private boolean mUseStrictPhoneNumberComparison;
5393a6a49cfb06272e3e25f3c390a9cf4002da6e34dDaisuke Miyakawa
540d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    /**
541d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton     * List of package names with access to {@link RawContacts#IS_RESTRICTED} data.
542d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton     */
543d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    private String[] mUnrestrictedPackages;
544d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton
545f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
546b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    public static synchronized ContactsDatabaseHelper getInstance(Context context) {
547b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (sSingleton == null) {
5482a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            sSingleton = new ContactsDatabaseHelper(context, DATABASE_NAME, true);
549b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
550b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return sSingleton;
551b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
552b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
5531f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    /**
55431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov     * Private constructor, callers except unit tests should obtain an instance through
55535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana     * {@link #getInstance(android.content.Context)} instead.
5561f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey     */
557b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    ContactsDatabaseHelper(Context context) {
5582a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        this(context, null, false);
5592a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
5602a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
5612a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private ContactsDatabaseHelper(
5622a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            Context context, String databaseName, boolean optimizationEnabled) {
5632a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        super(context, databaseName, null, DATABASE_VERSION);
5642a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mDatabaseOptimizationEnabled = optimizationEnabled;
565d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        Resources resources = context.getResources();
566619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
567b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        mContext = context;
56828b3769e3fcecae56c3fc70cbcb0f95282b9640eFred Quintana        mSyncState = new SyncStateContentProviderHelper();
569e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        mCountryMonitor = new CountryMonitor(context);
57036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        mUseStrictPhoneNumberComparison =
571d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                resources.getBoolean(
572d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                        com.android.internal.R.bool.config_use_strict_phone_number_comparation);
5730f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        int resourceId = resources.getIdentifier("unrestricted_packages", "array",
5740f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov                context.getPackageName());
5750f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        if (resourceId != 0) {
5760f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov            mUnrestrictedPackages = resources.getStringArray(resourceId);
5770f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        } else {
5780f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov            mUnrestrictedPackages = new String[0];
5790f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        }
580b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
581b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
5822a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private void refreshDatabaseCaches(SQLiteDatabase db) {
58378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateDelete = null;
58478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace = null;
58578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateInsert = null;
58678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateAutoTimestamp = null;
58778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusAttributionUpdate = null;
58878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts = null;
58978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate = null;
59078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement = null;
59178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement = null;
59278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement = null;
59378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert = null;
59478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupDelete = null;
59578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mPackageQuery = null;
59678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mPackageInsert = null;
59778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mDataMimetypeQuery = null;
59878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mActivitiesMimetypeQuery = null;
59978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mContactIdQuery = null;
60078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mAggregationModeQuery = null;
601f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        mContactInDefaultDirectoryQuery = null;
6022a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
6032a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimetypeCache.clear();
6042a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mPackageCache.clear();
6052a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
6062a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimetypeQuery = db.compileStatement(
6072a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                "SELECT " + MimetypesColumns._ID +
6082a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                " FROM " + Tables.MIMETYPES +
6092a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                " WHERE " + MimetypesColumns.MIMETYPE + "=?");
6102a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
6112a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimetypeInsert = db.compileStatement(
6122a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                "INSERT INTO " + Tables.MIMETYPES + "("
6132a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                        + MimetypesColumns.MIMETYPE +
6142a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                ") VALUES (?)");
6152a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
6162a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdEmail = getMimeTypeId(Email.CONTENT_ITEM_TYPE);
6172a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdIm = getMimeTypeId(Im.CONTENT_ITEM_TYPE);
618a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov        mMimeTypeIdSip = getMimeTypeId(SipAddress.CONTENT_ITEM_TYPE);
6192a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdStructuredName = getMimeTypeId(StructuredName.CONTENT_ITEM_TYPE);
6202a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdOrganization = getMimeTypeId(Organization.CONTENT_ITEM_TYPE);
6212a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdNickname = getMimeTypeId(Nickname.CONTENT_ITEM_TYPE);
6222a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdPhone = getMimeTypeId(Phone.CONTENT_ITEM_TYPE);
62378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
62478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
625b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
626b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onOpen(SQLiteDatabase db) {
6272a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        refreshDatabaseCaches(db);
62835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
62978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSyncState.onDatabaseOpened(db);
6301f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
6311f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        db.execSQL("ATTACH DATABASE ':memory:' AS " + DATABASE_PRESENCE + ";");
632e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS " + DATABASE_PRESENCE + "." + Tables.PRESENCE + " ("+
63382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.DATA_ID + " INTEGER PRIMARY KEY REFERENCES data(_id)," +
63482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.PROTOCOL + " INTEGER NOT NULL," +
63582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.CUSTOM_PROTOCOL + " TEXT," +
63682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.IM_HANDLE + " TEXT," +
63782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.IM_ACCOUNT + " TEXT," +
638a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                PresenceColumns.CONTACT_ID + " INTEGER REFERENCES contacts(_id)," +
639a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                PresenceColumns.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
64082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.PRESENCE + " INTEGER," +
641aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                StatusUpdates.CHAT_CAPABILITY + " INTEGER NOT NULL DEFAULT 0," +
64282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                "UNIQUE(" + StatusUpdates.PROTOCOL + ", " + StatusUpdates.CUSTOM_PROTOCOL
64382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                    + ", " + StatusUpdates.IM_HANDLE + ", " + StatusUpdates.IM_ACCOUNT + ")" +
6441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        ");");
6451f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
646e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE INDEX IF NOT EXISTS " + DATABASE_PRESENCE + ".presenceIndex" + " ON "
6474dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov                + Tables.PRESENCE + " (" + PresenceColumns.RAW_CONTACT_ID + ");");
64809562b6c3a420ded0d02b9bd2290de2dbab9e304Vasu Nori        db.execSQL("CREATE INDEX IF NOT EXISTS " + DATABASE_PRESENCE + ".presenceIndex2" + " ON "
64909562b6c3a420ded0d02b9bd2290de2dbab9e304Vasu Nori                + Tables.PRESENCE + " (" + PresenceColumns.CONTACT_ID + ");");
650e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov
651e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS "
652aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + DATABASE_PRESENCE + "." + Tables.AGGREGATED_PRESENCE + " ("+
653e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov                AggregatedPresenceColumns.CONTACT_ID
654e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov                        + " INTEGER PRIMARY KEY REFERENCES contacts(_id)," +
655632248ae0053fa99b1f5b4cfaab3e55b7453fcb1Vasu Nori                StatusUpdates.PRESENCE + " INTEGER," +
656aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                StatusUpdates.CHAT_CAPABILITY + " INTEGER NOT NULL DEFAULT 0" +
657e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        ");");
658bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
659bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
660bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_deleted"
661bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEFORE DELETE ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
662bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
663bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + "   DELETE FROM " + Tables.AGGREGATED_PRESENCE
664bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + "     WHERE " + AggregatedPresenceColumns.CONTACT_ID + " = " +
665bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        "(SELECT " + PresenceColumns.CONTACT_ID +
666bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " FROM " + Tables.PRESENCE +
667bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " WHERE " + PresenceColumns.RAW_CONTACT_ID
668bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                + "=OLD." + PresenceColumns.RAW_CONTACT_ID +
669bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " AND NOT EXISTS" +
670bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                "(SELECT " + PresenceColumns.RAW_CONTACT_ID +
671bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " FROM " + Tables.PRESENCE +
672bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " WHERE " + PresenceColumns.CONTACT_ID
673bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                        + "=OLD." + PresenceColumns.CONTACT_ID +
674bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " AND " + PresenceColumns.RAW_CONTACT_ID
675bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                        + "!=OLD." + PresenceColumns.RAW_CONTACT_ID + "));"
676bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
677bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
678aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori        final String replaceAggregatePresenceSql =
679aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                "INSERT OR REPLACE INTO " + Tables.AGGREGATED_PRESENCE + "("
680093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + AggregatedPresenceColumns.CONTACT_ID + ", "
681093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.PRESENCE + ", "
682093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.CHAT_CAPABILITY + ")"
683093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                + " SELECT "
684093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + PresenceColumns.CONTACT_ID + ","
685093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.PRESENCE + ","
686093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.CHAT_CAPABILITY
687aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " FROM " + Tables.PRESENCE
688aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " WHERE "
689093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + " (ifnull(" + StatusUpdates.PRESENCE + ",0)  * 10 "
690093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                            + "+ ifnull(" + StatusUpdates.CHAT_CAPABILITY + ", 0))"
691093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + " = (SELECT "
692093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + "MAX (ifnull(" + StatusUpdates.PRESENCE + ",0)  * 10 "
693093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                                + "+ ifnull(" + StatusUpdates.CHAT_CAPABILITY + ", 0))"
694093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + " FROM " + Tables.PRESENCE
695093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + " WHERE " + PresenceColumns.CONTACT_ID
696093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                            + "=NEW." + PresenceColumns.CONTACT_ID
697093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + ")"
698093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                + " AND " + PresenceColumns.CONTACT_ID + "=NEW." + PresenceColumns.CONTACT_ID + ";";
699bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
700bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_inserted"
701bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " AFTER INSERT ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
702bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
703bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + replaceAggregatePresenceSql
704bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
705bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
706bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_updated"
707bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " AFTER UPDATE ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
708bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
709bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + replaceAggregatePresenceSql
710bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
711b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
712b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
713b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
714b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onCreate(SQLiteDatabase db) {
715b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        Log.i(TAG, "Bootstrapping database");
716b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
71735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        mSyncState.createDatabase(db);
71835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
719b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // One row per group of contacts corresponding to the same person
720d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.CONTACTS + " (" +
721b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
722fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
723d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.PHOTO_ID + " INTEGER REFERENCES data(_id)," +
724d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.CUSTOM_RINGTONE + " TEXT," +
725d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," +
726d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," +
727d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.LAST_TIME_CONTACTED + " INTEGER," +
728d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.STARRED + " INTEGER NOT NULL DEFAULT 0," +
729f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov                Contacts.HAS_PHONE_NUMBER + " INTEGER NOT NULL DEFAULT 0," +
7305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                Contacts.LOOKUP_KEY + " TEXT," +
731a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                ContactsColumns.LAST_STATUS_UPDATE_ID + " INTEGER REFERENCES data(_id)," +
7324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.SINGLE_IS_RESTRICTED + " INTEGER NOT NULL DEFAULT 0" +
733b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
734b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
73554d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX contacts_has_phone_index ON " + Tables.CONTACTS + " (" +
73654d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                Contacts.HAS_PHONE_NUMBER +
73754d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
73854d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
73954d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX contacts_restricted_index ON " + Tables.CONTACTS + " (" +
74054d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                ContactsColumns.SINGLE_IS_RESTRICTED +
74154d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
74254d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
743fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_name_raw_contact_id_index ON " + Tables.CONTACTS + " (" +
744fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID +
745fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
746fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
747b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Contacts table
7485ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.RAW_CONTACTS + " (" +
7496cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
7506cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.IS_RESTRICTED + " INTEGER DEFAULT 0," +
7516cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.ACCOUNT_NAME + " STRING DEFAULT NULL, " +
7526cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + " STRING DEFAULT NULL, " +
7536cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.SOURCE_ID + " TEXT," +
75497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                RawContacts.RAW_CONTACT_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
7556cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.VERSION + " INTEGER NOT NULL DEFAULT 1," +
75673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov                RawContacts.DIRTY + " INTEGER NOT NULL DEFAULT 0," +
75733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov                RawContacts.DELETED + " INTEGER NOT NULL DEFAULT 0," +
75854d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                RawContacts.CONTACT_ID + " INTEGER REFERENCES contacts(_id)," +
7596cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.AGGREGATION_MODE + " INTEGER NOT NULL DEFAULT " +
7606cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                        RawContacts.AGGREGATION_MODE_DEFAULT + "," +
7618e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov                RawContactsColumns.AGGREGATION_NEEDED + " INTEGER NOT NULL DEFAULT 1," +
7626cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.CUSTOM_RINGTONE + " TEXT," +
7636cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," +
7646cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," +
7656cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.LAST_TIME_CONTACTED + " INTEGER," +
76633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov                RawContacts.STARRED + " INTEGER NOT NULL DEFAULT 0," +
7675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_PRIMARY + " TEXT," +
7685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_ALTERNATIVE + " TEXT," +
7695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_SOURCE + " INTEGER NOT NULL DEFAULT " +
77025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov                        DisplayNameSources.UNDEFINED + "," +
7715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.PHONETIC_NAME + " TEXT," +
7725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.PHONETIC_NAME_STYLE + " TEXT," +
773de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                RawContacts.SORT_KEY_PRIMARY + " TEXT COLLATE " +
774de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                        ContactsProvider2.PHONEBOOK_COLLATOR_NAME + "," +
775de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                RawContacts.SORT_KEY_ALTERNATIVE + " TEXT COLLATE " +
776de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                        ContactsProvider2.PHONEBOOK_COLLATOR_NAME + "," +
777f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                RawContacts.NAME_VERIFIED + " INTEGER NOT NULL DEFAULT 0," +
7783cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC1 + " TEXT, " +
7793cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC2 + " TEXT, " +
7803cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC3 + " TEXT, " +
7813cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC4 + " TEXT " +
782b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
783b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
78454d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contacts_contact_id_index ON " + Tables.RAW_CONTACTS + " (" +
78554d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                RawContacts.CONTACT_ID +
78654d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
78754d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
7885f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contacts_source_id_index ON " + Tables.RAW_CONTACTS + " (" +
7895f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.SOURCE_ID + ", " +
7905f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + ", " +
7915f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.ACCOUNT_NAME +
7925f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        ");");
7935f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov
794f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        // TODO readd the index and investigate a controlled use of it
795f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//        db.execSQL("CREATE INDEX raw_contacts_agg_index ON " + Tables.RAW_CONTACTS + " (" +
796f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//                RawContactsColumns.AGGREGATION_NEEDED +
797f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//        ");");
7988e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov
799b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Package name mapping table
800ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PACKAGES + " (" +
801ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                PackagesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
802ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                PackagesColumns.PACKAGE + " TEXT NOT NULL" +
803b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
804b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
805ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // Mimetype mapping table
806ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.MIMETYPES + " (" +
807ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                MimetypesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
808ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                MimetypesColumns.MIMETYPE + " TEXT NOT NULL" +
809b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
810b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
81108768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        // Mimetype table requires an index on mime type
81208768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX mime_type ON " + Tables.MIMETYPES + " (" +
81308768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov                MimetypesColumns.MIMETYPE +
81408768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        ");");
81508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
816b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Public generic data table
817b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.DATA + " (" +
818b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
81967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                DataColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
820b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                DataColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
82111944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                Data.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
82297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                Data.IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
823f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.IS_PRIMARY + " INTEGER NOT NULL DEFAULT 0," +
824f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.IS_SUPER_PRIMARY + " INTEGER NOT NULL DEFAULT 0," +
825f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA_VERSION + " INTEGER NOT NULL DEFAULT 0," +
826f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA1 + " TEXT," +
827f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA2 + " TEXT," +
828f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA3 + " TEXT," +
829f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA4 + " TEXT," +
830f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA5 + " TEXT," +
831f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA6 + " TEXT," +
832f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA7 + " TEXT," +
833f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA8 + " TEXT," +
834f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA9 + " TEXT," +
83567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA10 + " TEXT," +
83667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA11 + " TEXT," +
83767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA12 + " TEXT," +
83867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA13 + " TEXT," +
83967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA14 + " TEXT," +
8403cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.DATA15 + " TEXT," +
8413cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC1 + " TEXT, " +
8423cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC2 + " TEXT, " +
8433cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC3 + " TEXT, " +
8443cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC4 + " TEXT " +
845b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
846b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
84711944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        db.execSQL("CREATE INDEX data_raw_contact_id ON " + Tables.DATA + " (" +
84811944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                Data.RAW_CONTACT_ID +
84911944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        ");");
85011944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
85111944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        /**
85211944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov         * For email lookup and similar queries.
85311944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov         */
854f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov        db.execSQL("CREATE INDEX data_mimetype_data1_index ON " + Tables.DATA + " (" +
85511944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "," +
856f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov                Data.DATA1 +
85711944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        ");");
85811944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
859b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Private phone numbers table used for lookup
860b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" +
861f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.DATA_ID
862892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        + " INTEGER REFERENCES data(_id) NOT NULL," +
8635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID
8645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
86536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL," +
86636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL" +
867b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
868b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
869b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" +
870f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + "," +
871f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
872b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.DATA_ID +
873b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
874b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
87536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
87636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
87736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
87836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
87936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        ");");
88036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
881d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_data_id_min_match_index ON " + Tables.PHONE_LOOKUP +
882d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov                " (" + PhoneLookupColumns.DATA_ID + ", " + PhoneLookupColumns.MIN_MATCH + ");");
883d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov
884a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        // Private name/nickname table used for lookup
885a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.NAME_LOOKUP + " (" +
88614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                NameLookupColumns.DATA_ID
88714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                        + " INTEGER REFERENCES data(_id) NOT NULL," +
8885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID
8895ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
89011944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                NameLookupColumns.NORMALIZED_NAME + " TEXT NOT NULL," +
89111944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                NameLookupColumns.NAME_TYPE + " INTEGER NOT NULL," +
89214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                "PRIMARY KEY ("
89314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                        + NameLookupColumns.DATA_ID + ", "
89411944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                        + NameLookupColumns.NORMALIZED_NAME + ", "
89511944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                        + NameLookupColumns.NAME_TYPE + ")" +
896a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        ");");
897a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
89814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        db.execSQL("CREATE INDEX name_lookup_raw_contact_id_index ON " + Tables.NAME_LOOKUP + " (" +
89914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID +
90014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        ");");
90114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov
902b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.NICKNAME_LOOKUP + " (" +
903b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + " TEXT," +
904b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.CLUSTER + " TEXT" +
905b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        ");");
906b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
907b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX nickname_lookup_index ON " + Tables.NICKNAME_LOOKUP + " (" +
908b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + ", " +
909b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.CLUSTER +
910b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        ");");
911b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
912ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // Groups table
913ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.GROUPS + " (" +
914ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
91567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                GroupsColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
916035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana                Groups.ACCOUNT_NAME + " STRING DEFAULT NULL, " +
917035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana                Groups.ACCOUNT_TYPE + " STRING DEFAULT NULL, " +
918ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups.SOURCE_ID + " TEXT," +
9199261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                Groups.VERSION + " INTEGER NOT NULL DEFAULT 1," +
92073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov                Groups.DIRTY + " INTEGER NOT NULL DEFAULT 0," +
921ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups.TITLE + " TEXT," +
92267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Groups.TITLE_RES + " INTEGER," +
9230f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov                Groups.NOTES + " TEXT," +
9240f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov                Groups.SYSTEM_ID + " TEXT," +
92594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana                Groups.DELETED + " INTEGER NOT NULL DEFAULT 0," +
926eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Groups.GROUP_VISIBLE + " INTEGER NOT NULL DEFAULT 0," +
927ea547d55f864133861b2db44221ae0c2ac6c1a68Fred Quintana                Groups.SHOULD_SYNC + " INTEGER NOT NULL DEFAULT 1," +
928dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                Groups.AUTO_ADD + " INTEGER NOT NULL DEFAULT 0," +
929dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                Groups.FAVORITES + " INTEGER NOT NULL DEFAULT 0," +
930c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                Groups.GROUP_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
9313cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC1 + " TEXT, " +
9323cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC2 + " TEXT, " +
9333cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC3 + " TEXT, " +
9343cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC4 + " TEXT " +
935ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        ");");
936ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
9375f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        db.execSQL("CREATE INDEX groups_source_id_index ON " + Tables.GROUPS + " (" +
9385f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.SOURCE_ID + ", " +
9395f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.ACCOUNT_TYPE + ", " +
9405f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.ACCOUNT_NAME +
9415f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        ");");
9425f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov
943b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.AGGREGATION_EXCEPTIONS + " (" +
944b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                AggregationExceptionColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
945b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                AggregationExceptions.TYPE + " INTEGER NOT NULL, " +
9460c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1
9475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id), " +
9480c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2
9495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id)" +
950b0160a0bcf6d59eaa43fd501e124b95f873e0157Marc Blank        ");");
951b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
952b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index1 ON " +
953b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                Tables.AGGREGATION_EXCEPTIONS + " (" +
9540c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1 + ", " +
9550c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2 +
956b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        ");");
957b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
958b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index2 ON " +
959b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                Tables.AGGREGATION_EXCEPTIONS + " (" +
9600c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2 + ", " +
9610c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1 +
962b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        ");");
963b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
964eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.SETTINGS + " (" +
965eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.ACCOUNT_NAME + " STRING NOT NULL," +
966eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.ACCOUNT_TYPE + " STRING NOT NULL," +
967eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.UNGROUPED_VISIBLE + " INTEGER NOT NULL DEFAULT 0," +
968eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.SHOULD_SYNC + " INTEGER NOT NULL DEFAULT 1, " +
969eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                "PRIMARY KEY (" + Settings.ACCOUNT_NAME + ", " +
970e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    Settings.ACCOUNT_TYPE + ") ON CONFLICT REPLACE" +
971eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        ");");
972eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey
9734394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.VISIBLE_CONTACTS + " (" +
9744394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
9754394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
9764394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
977385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DEFAULT_DIRECTORY + " (" +
978385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
979385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        ");");
980385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
981e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        // The table for recent calls is here so we can do table joins
982e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        // on people, phones, and calls all in one place.
983e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.CALLS + " (" +
984e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
985e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.NUMBER + " TEXT," +
986e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.DATE + " INTEGER," +
987e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.DURATION + " INTEGER," +
988e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.TYPE + " INTEGER," +
989e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.NEW + " INTEGER," +
990e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NAME + " TEXT," +
991e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NUMBER_TYPE + " INTEGER," +
9922530512f639c4979fd7371c7dd25dd67e8118124Bai Tao                Calls.CACHED_NUMBER_LABEL + " TEXT," +
9932530512f639c4979fd7371c7dd25dd67e8118124Bai Tao                Calls.COUNTRY_ISO + " TEXT" + ");");
994e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov
995b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Activities table
996b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.ACTIVITIES + " (" +
997b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
99867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                ActivitiesColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
999b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                ActivitiesColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
1000b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.RAW_ID + " TEXT," +
1001499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.IN_REPLY_TO + " TEXT," +
10025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Activities.AUTHOR_CONTACT_ID +  " INTEGER REFERENCES raw_contacts(_id)," +
10035ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Activities.TARGET_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
1004b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.PUBLISHED + " INTEGER NOT NULL," +
1005499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.THREAD_PUBLISHED + " INTEGER NOT NULL," +
1006b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.TITLE + " TEXT NOT NULL," +
1007b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.SUMMARY + " TEXT," +
1008adb55c2d8295d300961d86a3605c8ddc469cd4a2Dmitri Plotnikov                Activities.LINK + " TEXT, " +
1009b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.THUMBNAIL + " BLOB" +
1010b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
1011b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1012a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.STATUS_UPDATES + " (" +
1013a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                StatusUpdatesColumns.DATA_ID + " INTEGER PRIMARY KEY REFERENCES data(_id)," +
10140a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS + " TEXT," +
10150a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_TIMESTAMP + " INTEGER," +
10160a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_RES_PACKAGE + " TEXT, " +
10170a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_LABEL + " INTEGER, " +
10180a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_ICON + " INTEGER" +
1019a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        ");");
1020a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov
1021b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.PROPERTIES + " (" +
1022b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_KEY + " TEXT PRIMARY KEY, " +
1023b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_VALUE + " TEXT " +
1024b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ");");
1025b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
1026743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.ACCOUNTS + " (" +
1027743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov                RawContacts.ACCOUNT_NAME + " TEXT, " +
1028743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + " TEXT " +
1029743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        ");");
1030743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
1031743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // Allow contacts without any account to be created for now.  Achieve that
1032743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // by inserting a fake account with both type and name as NULL.
1033743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // This "account" should be eliminated as soon as the first real writable account
1034743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // is added to the phone.
1035743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        db.execSQL("INSERT INTO accounts VALUES(NULL, NULL)");
1036743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
1037d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        createDirectoriesTable(db);
1038d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
1039a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        createContactsViews(db);
1040a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        createGroupsView(db);
1041fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        createContactsTriggers(db);
1042916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        createContactsIndexes(db);
10434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
1044a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        loadNicknameLookupTable(db);
1045a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1046a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        // Add the legacy API support views, etc
1047a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        LegacyApiSupport.createDatabase(db);
1048a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
10492a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        if (mDatabaseOptimizationEnabled) {
10502a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // This will create a sqlite_stat1 table that is used for query optimization
10512a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            db.execSQL("ANALYZE;");
1052a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
10532a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            updateSqliteStats(db);
1054a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
10552a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // We need to close and reopen the database connection so that the stats are
10562a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // taken into account. Make a note of it and do the actual reopening in the
10572a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // getWritableDatabase method.
10582a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            mReopenDatabase = true;
10592a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        }
1060a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1061a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        ContentResolver.requestSync(null /* all accounts */,
1062a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                ContactsContract.AUTHORITY, new Bundle());
1063a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    }
1064a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1065d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    private void createDirectoriesTable(SQLiteDatabase db) {
1066d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DIRECTORIES + "(" +
1067d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
1068d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.PACKAGE_NAME + " TEXT NOT NULL," +
1069d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.DIRECTORY_AUTHORITY + " TEXT NOT NULL," +
1070d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.TYPE_RESOURCE_ID + " INTEGER," +
1071e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov                DirectoryColumns.TYPE_RESOURCE_NAME + " TEXT," +
1072d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.ACCOUNT_TYPE + " TEXT," +
1073d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.ACCOUNT_NAME + " TEXT," +
1074d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.DISPLAY_NAME + " TEXT, " +
1075d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.EXPORT_SUPPORT + " INTEGER NOT NULL" +
107697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                        " DEFAULT " + Directory.EXPORT_SUPPORT_NONE + "," +
107797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                Directory.SHORTCUT_SUPPORT + " INTEGER NOT NULL" +
10783d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        " DEFAULT " + Directory.SHORTCUT_SUPPORT_NONE + "," +
10793d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                Directory.PHOTO_SUPPORT + " INTEGER NOT NULL" +
10803d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        " DEFAULT " + Directory.PHOTO_SUPPORT_NONE +
1081d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        ");");
1082d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
10833d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        // Trigger a full scan of directories in the system
10843d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        setProperty(db, ContactDirectoryManager.PROPERTY_DIRECTORY_SCAN_COMPLETE, "0");
1085d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    }
1086d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
1087916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    private static void createContactsTriggers(SQLiteDatabase db) {
1088fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1089fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        /*
1090fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * Automatically delete Data rows when a raw contact is deleted.
1091fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         */
1092fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.RAW_CONTACTS + "_deleted;");
1093fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_deleted "
1094fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   BEFORE DELETE ON " + Tables.RAW_CONTACTS
1095fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1096fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.DATA
1097fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Data.RAW_CONTACT_ID
1098fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID + ";"
1099fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.AGGREGATION_EXCEPTIONS
1100fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + AggregationExceptions.RAW_CONTACT_ID1
1101fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID
1102fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "        OR " + AggregationExceptions.RAW_CONTACT_ID2
1103fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID + ";"
110435da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "   DELETE FROM " + Tables.VISIBLE_CONTACTS
110535da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
110635da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
110735da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
110835da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "           )=1;"
1109385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "   DELETE FROM " + Tables.DEFAULT_DIRECTORY
1110385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
1111385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
1112385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
1113385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "           )=1;"
1114fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.CONTACTS
1115fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
1116fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
1117fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
1118fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "           )=1;"
1119fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1120fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1121fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1122fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS contacts_times_contacted;");
11236c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        db.execSQL("DROP TRIGGER IF EXISTS raw_contacts_times_contacted;");
1124fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1125fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        /*
1126fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * Triggers that update {@link RawContacts#VERSION} when the contact is
1127fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * marked for deletion or any time a data row is inserted, updated or
1128fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * deleted.
1129fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         */
1130fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.RAW_CONTACTS + "_marked_deleted;");
1131fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_marked_deleted "
11327f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori                + "   AFTER UPDATE ON " + Tables.RAW_CONTACTS
1133fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1134fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1135fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET "
1136fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                +         RawContacts.VERSION + "=OLD." + RawContacts.VERSION + "+1 "
1137fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + RawContacts._ID
1138fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "       AND NEW." + RawContacts.DELETED + "!= OLD." + RawContacts.DELETED + ";"
1139fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1140fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1141fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.DATA + "_updated;");
11427f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_updated AFTER UPDATE ON " + Tables.DATA
1143fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1144fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.DATA
1145fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + Data.DATA_VERSION + "=OLD." + Data.DATA_VERSION + "+1 "
1146fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Data._ID + "=OLD." + Data._ID + ";"
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                + " END");
1151fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1152fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.DATA + "_deleted;");
1153fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_deleted BEFORE DELETE ON " + Tables.DATA
1154fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1155fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1156fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + RawContacts.VERSION + "=" + RawContacts.VERSION + "+1 "
1157fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + Data.RAW_CONTACT_ID + ";"
1158fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.PHONE_LOOKUP
1159fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + PhoneLookupColumns.DATA_ID + "=OLD." + Data._ID + ";"
1160fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.STATUS_UPDATES
1161fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + StatusUpdatesColumns.DATA_ID + "=OLD." + Data._ID + ";"
1162fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.NAME_LOOKUP
1163fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + NameLookupColumns.DATA_ID + "=OLD." + Data._ID + ";"
1164fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1165fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1166fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1167fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.GROUPS + "_updated1;");
1168fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.GROUPS + "_updated1 "
11697f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori                + "   AFTER UPDATE ON " + Tables.GROUPS
1170fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1171fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.GROUPS
1172fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET "
1173fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                +         Groups.VERSION + "=OLD." + Groups.VERSION + "+1"
1174fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Groups._ID + "=OLD." + Groups._ID + ";"
1175fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1176fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov    }
1177fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1178916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    private static void createContactsIndexes(SQLiteDatabase db) {
1179916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
1180916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        db.execSQL("CREATE INDEX name_lookup_index ON " + Tables.NAME_LOOKUP + " (" +
1181916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.NORMALIZED_NAME + "," +
1182916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.NAME_TYPE + ", " +
1183916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID + ", " +
1184916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.DATA_ID +
1185916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        ");");
118604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
118704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS raw_contact_sort_key1_index");
118804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
118904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                RawContacts.SORT_KEY_PRIMARY +
119004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        ");");
119104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
119204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS raw_contact_sort_key2_index");
119304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key2_index ON " + Tables.RAW_CONTACTS + " (" +
119404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                RawContacts.SORT_KEY_ALTERNATIVE +
119504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        ");");
1196916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    }
1197916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov
1198a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    private static void createContactsViews(SQLiteDatabase db) {
1199a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.CONTACTS_ALL + ";");
1200a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.CONTACTS_RESTRICTED + ";");
1201a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.DATA_ALL + ";");
1202a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.DATA_RESTRICTED + ";");
1203a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_CONTACTS_ALL + ";");
1204a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_CONTACTS_RESTRICTED + ";");
1205a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_ENTITIES + ";");
1206a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_ENTITIES_RESTRICTED + ";");
1207a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.ENTITIES + ";");
1208a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.ENTITIES_RESTRICTED + ";");
1209a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
12104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String dataColumns =
12114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                Data.IS_PRIMARY + ", "
12124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.IS_SUPER_PRIMARY + ", "
12134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA_VERSION + ", "
12144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + PackagesColumns.PACKAGE + " AS " + Data.RES_PACKAGE + ","
12154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + MimetypesColumns.MIMETYPE + " AS " + Data.MIMETYPE + ", "
121697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + Data.IS_READ_ONLY + ", "
12174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA1 + ", "
12184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA2 + ", "
12194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA3 + ", "
12204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA4 + ", "
12214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA5 + ", "
12224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA6 + ", "
12234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA7 + ", "
12244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA8 + ", "
12254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA9 + ", "
12264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA10 + ", "
12274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA11 + ", "
12284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA12 + ", "
12294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA13 + ", "
12304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA14 + ", "
12314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA15 + ", "
12324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC1 + ", "
12334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC2 + ", "
12344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC3 + ", "
12354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC4;
12364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String syncColumns =
12384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AS " + RawContacts.ACCOUNT_NAME + ","
12394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AS " + RawContacts.ACCOUNT_TYPE + ","
12404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SOURCE_ID + " AS " + RawContacts.SOURCE_ID + ","
1241f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                + RawContactsColumns.CONCRETE_NAME_VERIFIED + " AS " + RawContacts.NAME_VERIFIED + ","
12424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_VERSION + " AS " + RawContacts.VERSION + ","
12434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DIRTY + " AS " + RawContacts.DIRTY + ","
12444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC1 + " AS " + RawContacts.SYNC1 + ","
12454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC2 + " AS " + RawContacts.SYNC2 + ","
12464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC3 + " AS " + RawContacts.SYNC3 + ","
12474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC4 + " AS " + RawContacts.SYNC4;
12484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12493d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        String baseContactColumns =
12503d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                Contacts.HAS_PHONE_NUMBER + ", "
12513d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.NAME_RAW_CONTACT_ID + ", "
12523d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.LOOKUP_KEY + ", "
12533d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.PHOTO_ID + ", "
12543d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Clauses.CONTACT_VISIBLE + " AS " + Contacts.IN_VISIBLE_GROUP + ", "
12553d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + ContactsColumns.LAST_STATUS_UPDATE_ID;
12563d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
12574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactOptionColumns =
12584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.CONCRETE_CUSTOM_RINGTONE
12594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.CUSTOM_RINGTONE + ","
12604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL
12614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.SEND_TO_VOICEMAIL + ","
12624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_LAST_TIME_CONTACTED
12634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.LAST_TIME_CONTACTED + ","
12644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_TIMES_CONTACTED
12654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.TIMES_CONTACTED + ","
12664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_STARRED
12674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.STARRED;
12684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String contactNameColumns =
12705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "name_raw_contact." + RawContacts.DISPLAY_NAME_SOURCE
12715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_SOURCE + ", "
12725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.DISPLAY_NAME_PRIMARY
12735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_PRIMARY + ", "
12745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.DISPLAY_NAME_ALTERNATIVE
12755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_ALTERNATIVE + ", "
12765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.PHONETIC_NAME
12775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.PHONETIC_NAME + ", "
12785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.PHONETIC_NAME_STYLE
12795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.PHONETIC_NAME_STYLE + ", "
12805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.SORT_KEY_PRIMARY
12815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.SORT_KEY_PRIMARY + ", "
12825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.SORT_KEY_ALTERNATIVE
12834394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        + " AS " + Contacts.SORT_KEY_ALTERNATIVE;
12845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
12854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String dataSelect = "SELECT "
12864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + Data._ID + ","
12874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.RAW_CONTACT_ID + ", "
1288fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + RawContacts.CONTACT_ID + ", "
12894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + syncColumns + ", "
12904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + dataColumns + ", "
12914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + contactOptionColumns + ", "
12925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + contactNameColumns + ", "
12933d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + baseContactColumns + ", "
12943d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
12953d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_URI) + ", "
12963d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
12973d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_THUMBNAIL_URI) + ", "
12984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
12994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.DATA
1300a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.MIMETYPES + " ON ("
13014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1302a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " ON ("
13034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1304a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.CONTACTS + " ON ("
1305fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   RawContactsColumns.CONCRETE_CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID + ")"
1306fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1307fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")"
1308a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1309a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
13104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
13114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1312f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1313a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                        + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
13144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.DATA_ALL + " AS " + dataSelect);
13164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.DATA_RESTRICTED + " AS " + dataSelect + " WHERE "
1317fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0");
13184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String rawContactOptionColumns =
13204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                RawContacts.CUSTOM_RINGTONE + ","
13214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.SEND_TO_VOICEMAIL + ","
13224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.LAST_TIME_CONTACTED + ","
13234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.TIMES_CONTACTED + ","
13244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.STARRED;
13254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String rawContactsSelect = "SELECT "
13274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + RawContacts._ID + ","
13284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.CONTACT_ID + ", "
13294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.AGGREGATION_MODE + ", "
133097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + RawContacts.RAW_CONTACT_IS_READ_ONLY + ", "
13314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.DELETED + ", "
13325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_SOURCE  + ", "
13335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_PRIMARY  + ", "
13345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_ALTERNATIVE  + ", "
13355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.PHONETIC_NAME  + ", "
13365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.PHONETIC_NAME_STYLE  + ", "
13375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.SORT_KEY_PRIMARY  + ", "
13385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.SORT_KEY_ALTERNATIVE + ", "
13394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + rawContactOptionColumns + ", "
13404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + syncColumns
13414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS;
13424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_CONTACTS_ALL + " AS " + rawContactsSelect);
13444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_CONTACTS_RESTRICTED + " AS " + rawContactsSelect
13454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " WHERE " + RawContacts.IS_RESTRICTED + "=0");
13464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactsColumns =
13484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.CONCRETE_CUSTOM_RINGTONE
13494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.CUSTOM_RINGTONE + ", "
13505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + contactNameColumns + ", "
13513d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + baseContactColumns + ", "
13524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_LAST_TIME_CONTACTED
13534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.LAST_TIME_CONTACTED + ", "
13544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL
13554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.SEND_TO_VOICEMAIL + ", "
13564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_STARRED
13574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.STARRED + ", "
13584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_TIMES_CONTACTED
13593d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        + " AS " + Contacts.TIMES_CONTACTED;
13604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactsSelect = "SELECT "
13624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_ID + " AS " + Contacts._ID + ","
13633d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + contactsColumns + ", "
13643d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(ContactsColumns.CONCRETE_ID, Contacts.PHOTO_URI) + ", "
13653d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(ContactsColumns.CONCRETE_ID, Contacts.PHOTO_THUMBNAIL_URI)
13664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.CONTACTS
1367fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1368fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")";
13694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.CONTACTS_ALL + " AS " + contactsSelect);
1371fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.CONTACTS_RESTRICTED + " AS " + contactsSelect
1372fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " WHERE " + ContactsColumns.SINGLE_IS_RESTRICTED + "=0");
1373a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1374a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        String rawEntitiesSelect = "SELECT "
1375a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContacts.CONTACT_ID + ", "
1376a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DELETED + " AS " + RawContacts.DELETED + ","
1377a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + dataColumns + ", "
1378a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + syncColumns + ", "
1379a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC1 + ", "
1380a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC2 + ", "
1381a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC3 + ", "
1382a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC4 + ", "
1383a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + RawContacts._ID + ", "
1384a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + RawContacts.Entity.DATA_ID + ","
1385a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_STARRED + " AS " + RawContacts.STARRED + ","
1386a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED + " AS "
1387a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                        + RawContacts.IS_RESTRICTED + ","
1388a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
1389a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS
1390a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.DATA + " ON ("
1391a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1392a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1393a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
1394a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.MIMETYPES + " ON ("
1395a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1396a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
1397a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1398a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1399a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
1400a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1401a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_ENTITIES + " AS "
1402a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + rawEntitiesSelect);
1403a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_ENTITIES_RESTRICTED + " AS "
1404a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + rawEntitiesSelect + " WHERE " + RawContacts.IS_RESTRICTED + "=0");
1405a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1406a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        String entitiesSelect = "SELECT "
1407a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + Contacts._ID + ", "
1408a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + RawContacts.CONTACT_ID + ", "
1409a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DELETED + " AS " + RawContacts.DELETED + ","
1410a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED
1411a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                        + " AS " + RawContacts.IS_RESTRICTED + ","
1412a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + dataColumns + ", "
1413a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + syncColumns + ", "
1414a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + contactsColumns + ", "
14153d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
14163d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_URI) + ", "
14173d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
14183d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_THUMBNAIL_URI) + ", "
1419a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC1 + ", "
1420a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC2 + ", "
1421a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC3 + ", "
1422a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC4 + ", "
1423a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + Contacts.Entity.RAW_CONTACT_ID + ", "
1424a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + Contacts.Entity.DATA_ID + ","
1425a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
1426a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS
1427a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " JOIN " + Tables.CONTACTS + " ON ("
1428a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   RawContactsColumns.CONCRETE_CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID + ")"
1429a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1430a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")"
1431a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.DATA + " ON ("
1432a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1433a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1434a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
1435a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.MIMETYPES + " ON ("
1436a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1437a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
1438a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1439a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1440a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
1441a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1442a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.ENTITIES + " AS "
1443a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + entitiesSelect);
1444a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.ENTITIES_RESTRICTED + " AS "
1445a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + entitiesSelect + " WHERE " + RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0");
1446a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    }
14474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
14483d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    private static String buildPhotoUriAlias(String contactIdColumn, String alias) {
14492b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        return "(CASE WHEN " + Contacts.PHOTO_ID + " IS NULL"
14502b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " OR " + Contacts.PHOTO_ID + "=0"
14512b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " THEN NULL"
14522b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " ELSE " + "'" + Contacts.CONTENT_URI + "/'||"
14532b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                        + contactIdColumn + "|| '/" + Photo.CONTENT_DIRECTORY + "'"
14542b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " END)"
14552b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " AS " + alias;
14563d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
14573d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
1458a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    private static void createGroupsView(SQLiteDatabase db) {
1459a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.GROUPS_ALL + ";");
146089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        String groupsColumns =
146189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                Groups.ACCOUNT_NAME + ","
146289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.ACCOUNT_TYPE + ","
146389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SOURCE_ID + ","
146489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.VERSION + ","
146589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.DIRTY + ","
146689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.TITLE + ","
146789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.TITLE_RES + ","
146889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.NOTES + ","
146989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYSTEM_ID + ","
147089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.DELETED + ","
147189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.GROUP_VISIBLE + ","
147289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SHOULD_SYNC + ","
1473dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + Groups.AUTO_ADD + ","
1474dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + Groups.FAVORITES + ","
1475c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                + Groups.GROUP_IS_READ_ONLY + ","
147689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC1 + ","
147789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC2 + ","
147889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC3 + ","
147989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC4 + ","
148089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + PackagesColumns.PACKAGE + " AS " + Groups.RES_PACKAGE;
148189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
148289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        String groupsSelect = "SELECT "
148389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + GroupsColumns.CONCRETE_ID + " AS " + Groups._ID + ","
148489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + groupsColumns
148589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + " FROM " + Tables.GROUPS_JOIN_PACKAGES;
148689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
148789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.GROUPS_ALL + " AS " + groupsSelect);
1488b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
1489b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1490b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
1491b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
149246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion < 99) {
149346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion
149446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana                    + ", data will be lost!");
149546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
149646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.CONTACTS + ";");
149746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.RAW_CONTACTS + ";");
149846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.PACKAGES + ";");
149946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.MIMETYPES + ";");
150046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.DATA + ";");
150146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.PHONE_LOOKUP + ";");
150246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.NAME_LOOKUP + ";");
150346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.NICKNAME_LOOKUP + ";");
150446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.GROUPS + ";");
150546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.ACTIVITIES + ";");
150646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.CALLS + ";");
150746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.SETTINGS + ";");
150846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.STATUS_UPDATES + ";");
150946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
151046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // TODO: we should not be dropping agg_exceptions and contact_options. In case that
151146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // table's schema changes, we should try to preserve the data, because it was entered
151246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // by the user and has never been synched to the server.
151346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.AGGREGATION_EXCEPTIONS + ";");
151446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
151546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            onCreate(db);
151646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            return;
151746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
1518f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
151946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion);
1520a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
152108e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        boolean upgradeViewsAndTriggers = false;
152204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        boolean upgradeNameLookup = false;
15238d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov        boolean upgradeLegacyApiSupport = false;
152408e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov
152546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion == 99) {
152608e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
152746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            oldVersion++;
152846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
152946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
1530a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        if (oldVersion == 100) {
1531a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            db.execSQL("CREATE INDEX IF NOT EXISTS mimetypes_mimetype_index ON "
1532a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                    + Tables.MIMETYPES + " ("
1533a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                            + MimetypesColumns.MIMETYPE + ","
1534a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                            + MimetypesColumns._ID + ");");
1535a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            updateIndexStats(db, Tables.MIMETYPES,
1536a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                    "mimetypes_mimetype_index", "50 1 1");
1537a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
153808e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1539a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            oldVersion++;
1540a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        }
1541a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1542fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        if (oldVersion == 101) {
154308e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1544fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov            oldVersion++;
1545fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        }
1546fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
154747ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov        if (oldVersion == 102) {
154808e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
154947ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov            oldVersion++;
155047ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov        }
155147ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov
155236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        if (oldVersion == 103) {
155308e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1554bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey            oldVersion++;
1555bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey        }
1556bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey
155771037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov        if (oldVersion == 104 || oldVersion == 201) {
155871037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov            LegacyApiSupport.createSettingsTable(db);
155908e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
15603410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov            oldVersion++;
15613410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov        }
15623410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov
156371037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov        if (oldVersion == 105) {
15645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion202(db);
156504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            upgradeNameLookup = true;
15663410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov            oldVersion = 202;
156736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        }
156836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
1569fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        if (oldVersion == 202) {
15705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion203(db);
157108e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1572fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov            oldVersion++;
1573fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        }
1574fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
15759b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori        if (oldVersion == 203) {
157608e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
15779b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori            oldVersion++;
15789b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori        }
15799b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori
15805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (oldVersion == 204) {
15815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion205(db);
158208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
15835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            oldVersion++;
15845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
15855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
1586f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        if (oldVersion == 205) {
1587f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            upgrateToVersion206(db);
1588f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1589f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            oldVersion++;
1590f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        }
1591f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov
159231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        if (oldVersion == 206) {
1593b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeToVersion300(db);
159434469970fb04b9b188b5430f592b0c956a6ea2aaDmitri Plotnikov            oldVersion = 300;
159531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
159631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
15976c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        if (oldVersion == 300) {
15986c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook            upgradeViewsAndTriggers = true;
15996c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook            oldVersion = 301;
16006c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        }
16016c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook
1602916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        if (oldVersion == 301) {
1603916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1604916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            oldVersion = 302;
1605916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        }
1606916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov
1607b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (oldVersion == 302) {
1608b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeEmailToVersion303(db);
1609b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeNicknameToVersion303(db);
1610b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            oldVersion = 303;
1611b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
1612b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
161308768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        if (oldVersion == 303) {
161408768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            upgradeToVersion304(db);
161508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            oldVersion = 304;
161608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        }
161708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
1618f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        if (oldVersion == 304) {
1619f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee            upgradeNameLookup = true;
1620f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee            oldVersion = 305;
1621f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        }
1622f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee
162360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        if (oldVersion == 305) {
162460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            upgradeToVersion306(db);
162560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            oldVersion = 306;
162660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        }
162760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
1628b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        if (oldVersion == 306) {
1629b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            upgradeToVersion307(db);
1630b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            oldVersion = 307;
1631b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        }
1632b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
1633743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        if (oldVersion == 307) {
1634743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov            upgradeToVersion308(db);
1635743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov            oldVersion = 308;
1636743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        }
1637743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
163894c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        // Gingerbread upgrades
163994c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        if (oldVersion < 350) {
1640afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann            upgradeViewsAndTriggers = true;
164194c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            oldVersion = 351;
1642afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann        }
1643afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann
164494c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        if (oldVersion == 351) {
164594c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            upgradeNameLookup = true;
164694c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            oldVersion = 352;
164780d7871ca31d604cbfd857661d5300bb090076dbDaniel Lehmann        }
164880d7871ca31d604cbfd857661d5300bb090076dbDaniel Lehmann
16497da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        if (oldVersion == 352) {
16507da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            upgradeToVersion353(db);
16517da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            oldVersion = 353;
16527da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        }
16537da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
1654f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        // Honeycomb upgrades
1655f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        if (oldVersion < 400) {
1656dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana            upgradeViewsAndTriggers = true;
1657f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov            upgradeToVersion400(db);
1658f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov            oldVersion = 400;
1659dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        }
1660dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana
1661f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        if (oldVersion == 400) {
16624394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            upgradeViewsAndTriggers = true;
16634394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            upgradeToVersion401(db);
16644394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            oldVersion = 401;
16654394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        }
16664394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
1667d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        if (oldVersion == 401) {
1668d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov            upgradeToVersion402(db);
1669d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov            oldVersion = 402;
1670d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        }
1671d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
167297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        if (oldVersion == 402) {
167397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            upgradeViewsAndTriggers = true;
167497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            upgradeToVersion403(db);
167597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            oldVersion = 403;
167697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        }
167797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
1678a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        if (oldVersion == 403) {
1679a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1680a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov            oldVersion = 404;
1681a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        }
1682a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1683892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (oldVersion == 404) {
1684892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1685892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            upgradeToVersion405(db);
1686892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            oldVersion = 405;
1687892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
1688892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
16892530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        if (oldVersion == 405) {
16902530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            upgradeViewsAndTriggers = true;
16912530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            upgradeToVersion406(db);
16922530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            oldVersion = 406;
16932530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        }
16942530512f639c4979fd7371c7dd25dd67e8118124Bai Tao
1695cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov        if (oldVersion == 406) {
1696cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1697cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov            oldVersion = 407;
1698cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov        }
1699cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov
1700385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        if (oldVersion == 407) {
1701d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            // Obsolete
1702385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            oldVersion = 408;
1703385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        }
1704385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
17053d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        if (oldVersion == 408) {
17063d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            upgradeViewsAndTriggers = true;
17073d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            upgradeToVersion409(db);
17083d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            oldVersion = 409;
17093d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        }
17103d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
17112b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        if (oldVersion == 409) {
17122b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov            upgradeViewsAndTriggers = true;
17132b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov            oldVersion = 410;
17142b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        }
17152b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov
1716d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        if (oldVersion == 410) {
1717d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            upgradeToVersion411(db);
1718d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            oldVersion = 411;
1719d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        }
1720d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov
17217da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        if (oldVersion == 411) {
17227da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            // Same upgrade as 353, only on Honeycomb devices
17237da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            upgradeToVersion353(db);
17247da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            oldVersion = 412;
17257da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        }
17267da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
1727e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov        if (oldVersion == 412) {
1728e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov            upgradeToVersion413(db);
1729e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov            oldVersion = 413;
1730e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov        }
1731e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov
173256f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee        if (oldVersion == 413) {
173356f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee            upgradeNameLookup = true;
173456f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee            oldVersion = 414;
173556f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee        }
173656f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee
1737c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        if (oldVersion == 414) {
1738c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            upgradeToVersion415(db);
1739c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1740c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            oldVersion = 415;
1741c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        }
1742c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov
1743d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov        if (oldVersion == 415) {
1744d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov            upgradeToVersion416(db);
1745d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov            oldVersion = 416;
1746d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov        }
1747d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov
17488d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov        if (oldVersion == 416) {
17498d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov            upgradeLegacyApiSupport = true;
17508d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov            oldVersion = 417;
17518d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov        }
17528d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov
175308e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        if (upgradeViewsAndTriggers) {
175408e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createContactsViews(db);
175508e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createGroupsView(db);
175608e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createContactsTriggers(db);
1757916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            createContactsIndexes(db);
1758916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            updateSqliteStats(db);
17598d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov            upgradeLegacyApiSupport = true;
1760916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            mReopenDatabase = true;
176108e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        }
176208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov
17638d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov        if (upgradeLegacyApiSupport) {
17648d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov            LegacyApiSupport.createViews(db);
17658d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov        }
17668d2a74522d7b6f792edc74742b594fcb5251fbe2Dmitri Plotnikov
176704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (upgradeNameLookup) {
176804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            rebuildNameLookup(db);
176904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
177004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
177146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion != newVersion) {
177246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            throw new IllegalStateException(
177346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana                    "error upgrading the database to version " + newVersion);
177446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
1775b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
1776b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
17775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion202(SQLiteDatabase db) {
177836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL(
177936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "ALTER TABLE " + Tables.PHONE_LOOKUP +
178036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " ADD " + PhoneLookupColumns.MIN_MATCH + " TEXT;");
178136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
178236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
178336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
178436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
178536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
178636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        ");");
178736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
178836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        updateIndexStats(db, Tables.PHONE_LOOKUP,
178936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "phone_lookup_min_match_index", "10000 2 2 1");
179036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
179136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        SQLiteStatement update = db.compileStatement(
179236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "UPDATE " + Tables.PHONE_LOOKUP +
179336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " SET " + PhoneLookupColumns.MIN_MATCH + "=?" +
179436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " WHERE " + PhoneLookupColumns.DATA_ID + "=?");
179536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
179636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        // Populate the new column
179736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        Cursor c = db.query(Tables.PHONE_LOOKUP + " JOIN " + Tables.DATA +
179836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " ON (" + PhoneLookupColumns.DATA_ID + "=" + DataColumns.CONCRETE_ID + ")",
179936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                new String[]{Data._ID, Phone.NUMBER}, null, null, null, null, null);
180036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        try {
180136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            while (c.moveToNext()) {
180236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                long dataId = c.getLong(0);
180336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                String number = c.getString(1);
180436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                if (!TextUtils.isEmpty(number)) {
180536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.bindString(1, PhoneNumberUtils.toCallerIDMinMatch(number));
180636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.bindLong(2, dataId);
180736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.execute();
180836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                }
180936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            }
181036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        } finally {
181136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            c.close();
181236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        }
181336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    }
181436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
18155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion203(SQLiteDatabase db) {
1816758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // Garbage-collect first. A bug in Eclair was sometimes leaving
1817758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // raw_contacts in the database that no longer had contacts associated
1818758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // with them.  To avoid failures during this database upgrade, drop
1819758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // the orphaned raw_contacts.
1820758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        db.execSQL(
1821758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                "DELETE FROM raw_contacts" +
1822758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                " WHERE contact_id NOT NULL" +
1823758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                " AND contact_id NOT IN (SELECT _id FROM contacts)");
1824758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov
1825fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1826fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "ALTER TABLE " + Tables.CONTACTS +
1827fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " ADD " + Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)");
1828fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1829fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "ALTER TABLE " + Tables.RAW_CONTACTS +
18304394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " ADD contact_in_visible_group INTEGER NOT NULL DEFAULT 0");
1831fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1832fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // For each Contact, find the RawContact that contributed the display name
1833fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1834fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1835fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.NAME_RAW_CONTACT_ID + "=(" +
1836fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " SELECT " + RawContacts._ID +
1837fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.RAW_CONTACTS +
1838fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
1839fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " AND " + RawContactsColumns.CONCRETE_DISPLAY_NAME + "=" +
1840fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                                Tables.CONTACTS + "." + Contacts.DISPLAY_NAME +
1841fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " ORDER BY " + RawContacts._ID +
1842fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " LIMIT 1)"
1843fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1844fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1845fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_name_raw_contact_id_index ON " + Tables.CONTACTS + " (" +
1846fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID +
1847fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1848fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1849fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // If for some unknown reason we missed some names, let's make sure there are
1850fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // no contacts without a name, picking a raw contact "at random".
1851fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1852fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1853fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.NAME_RAW_CONTACT_ID + "=(" +
1854fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " SELECT " + RawContacts._ID +
1855fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.RAW_CONTACTS +
1856fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
1857fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " ORDER BY " + RawContacts._ID +
1858fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " LIMIT 1)" +
1859fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " WHERE " + Contacts.NAME_RAW_CONTACT_ID + " IS NULL"
1860fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1861fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1862fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // Wipe out DISPLAY_NAME on the Contacts table as it is no longer in use.
1863fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1864fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1865fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.DISPLAY_NAME + "=NULL"
1866fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1867fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1868fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // Copy the IN_VISIBLE_GROUP flag down to all raw contacts to allow
1869fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // indexing on (display_name, in_visible_group)
1870fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1871fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.RAW_CONTACTS +
18724394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " SET contact_in_visible_group=(" +
1873fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        "SELECT " + Contacts.IN_VISIBLE_GROUP +
1874fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.CONTACTS +
1875bcbd6a5cdd2d1aa6531c592428dc20e0282486c3Dmitri Plotnikov                        " WHERE " + Contacts._ID + "=" + RawContacts.CONTACT_ID + ")" +
1876bcbd6a5cdd2d1aa6531c592428dc20e0282486c3Dmitri Plotnikov                " WHERE " + RawContacts.CONTACT_ID + " NOT NULL"
1877fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1878fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1879fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
18804394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
1881fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                RawContactsColumns.DISPLAY_NAME + " COLLATE LOCALIZED ASC" +
1882fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1883fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1884fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("DROP INDEX contacts_visible_index");
1885fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_visible_index ON " + Tables.CONTACTS + " (" +
1886fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.IN_VISIBLE_GROUP +
1887fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1888fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov    }
1889fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
18905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion205(SQLiteDatabase db) {
18915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
18925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.DISPLAY_NAME_ALTERNATIVE + " TEXT;");
18935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
18945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.PHONETIC_NAME + " TEXT;");
18955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
18965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.PHONETIC_NAME_STYLE + " INTEGER;");
18975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
1898de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " ADD " + RawContacts.SORT_KEY_PRIMARY
1899de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " TEXT COLLATE " + ContactsProvider2.PHONEBOOK_COLLATOR_NAME + ";");
19005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
1901de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " ADD " + RawContacts.SORT_KEY_ALTERNATIVE
1902de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " TEXT COLLATE " + ContactsProvider2.PHONEBOOK_COLLATOR_NAME + ";");
19035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        final Locale locale = Locale.getDefault();
19055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
190651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        NameSplitter splitter = createNameSplitter();
19075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement rawContactUpdate = db.compileStatement(
19095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.RAW_CONTACTS +
19105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
19115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.DISPLAY_NAME_PRIMARY + "=?," +
19125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," +
19135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.PHONETIC_NAME + "=?," +
19145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.PHONETIC_NAME_STYLE + "=?," +
19155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.SORT_KEY_PRIMARY + "=?," +
19165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.SORT_KEY_ALTERNATIVE + "=?" +
19175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + RawContacts._ID + "=?");
19185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        upgradeStructuredNamesToVersion205(db, rawContactUpdate, splitter);
19205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        upgradeOrganizationsToVersion205(db, rawContactUpdate, splitter);
19215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("DROP INDEX raw_contact_sort_key1_index");
19235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
19244394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
19255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.SORT_KEY_PRIMARY +
19265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        ");");
19275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key2_index ON " + Tables.RAW_CONTACTS + " (" +
19294394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
19305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.SORT_KEY_ALTERNATIVE +
19315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        ");");
19325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
19335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private interface StructName205Query {
19355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String TABLE = Tables.DATA_JOIN_RAW_CONTACTS;
19365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String COLUMNS[] = {
19385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.CONCRETE_ID,
19395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Data.RAW_CONTACT_ID,
19405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_SOURCE,
19415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_PRIMARY,
19425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PREFIX,
19435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.GIVEN_NAME,
19445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.MIDDLE_NAME,
19455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.FAMILY_NAME,
19465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.SUFFIX,
19475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_FAMILY_NAME,
19485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_MIDDLE_NAME,
19495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_GIVEN_NAME,
19505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        };
19515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int ID = 0;
19535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int RAW_CONTACT_ID = 1;
19545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int DISPLAY_NAME_SOURCE = 2;
19555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int DISPLAY_NAME = 3;
19565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PREFIX = 4;
19575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int GIVEN_NAME = 5;
19585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int MIDDLE_NAME = 6;
19595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int FAMILY_NAME = 7;
19605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int SUFFIX = 8;
19615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_FAMILY_NAME = 9;
19625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_MIDDLE_NAME = 10;
19635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_GIVEN_NAME = 11;
19645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
19655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeStructuredNamesToVersion205(SQLiteDatabase db,
19675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement rawContactUpdate, NameSplitter splitter) {
19685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        // Process structured names to detect the style of the full name and phonetic name
19705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        long mMimeType;
19725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
19735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            mMimeType = DatabaseUtils.longForQuery(db,
19745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    "SELECT " + MimetypesColumns._ID +
19755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    " FROM " + Tables.MIMETYPES +
19765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    " WHERE " + MimetypesColumns.MIMETYPE
19775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                            + "='" + StructuredName.CONTENT_ITEM_TYPE + "'", null);
19785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } catch (SQLiteDoneException e) {
19795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            // No structured names in the database
19805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            return;
19815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
19825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement structuredNameUpdate = db.compileStatement(
19845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.DATA +
19855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
19865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.FULL_NAME_STYLE + "=?," +
19875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.DISPLAY_NAME + "=?," +
19885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.PHONETIC_NAME_STYLE + "=?" +
19895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + Data._ID + "=?");
19905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        NameSplitter.Name name = new NameSplitter.Name();
19925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        StringBuilder sb = new StringBuilder();
19935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        Cursor cursor = db.query(StructName205Query.TABLE,
19945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructName205Query.COLUMNS,
19955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=" + mMimeType, null, null, null, null);
19965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
19975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            while (cursor.moveToNext()) {
19985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long dataId = cursor.getLong(StructName205Query.ID);
19995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long rawContactId = cursor.getLong(StructName205Query.RAW_CONTACT_ID);
20005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                int displayNameSource = cursor.getInt(StructName205Query.DISPLAY_NAME_SOURCE);
20015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String displayName = cursor.getString(StructName205Query.DISPLAY_NAME);
20025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.clear();
20045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.prefix = cursor.getString(StructName205Query.PREFIX);
20055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.givenNames = cursor.getString(StructName205Query.GIVEN_NAME);
20065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.middleName = cursor.getString(StructName205Query.MIDDLE_NAME);
20075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.familyName = cursor.getString(StructName205Query.FAMILY_NAME);
20085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.suffix = cursor.getString(StructName205Query.SUFFIX);
20095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticFamilyName = cursor.getString(StructName205Query.PHONETIC_FAMILY_NAME);
20105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticMiddleName = cursor.getString(StructName205Query.PHONETIC_MIDDLE_NAME);
20115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticGivenName = cursor.getString(StructName205Query.PHONETIC_GIVEN_NAME);
20125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                upgradeNameToVersion205(dataId, rawContactId, displayNameSource, displayName, name,
20145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        structuredNameUpdate, rawContactUpdate, splitter, sb);
20155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
20165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } finally {
20175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            cursor.close();
20185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
20195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
20205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeNameToVersion205(long dataId, long rawContactId, int displayNameSource,
20225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String currentDisplayName, NameSplitter.Name name,
20235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement structuredNameUpdate, SQLiteStatement rawContactUpdate,
20245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            NameSplitter splitter, StringBuilder sb) {
20255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        splitter.guessNameStyle(name);
2027ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        int unadjustedFullNameStyle = name.fullNameStyle;
20285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        name.fullNameStyle = splitter.getAdjustedFullNameStyle(name.fullNameStyle);
20295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String displayName = splitter.join(name, true);
20305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
2031ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        // Don't update database with the adjusted fullNameStyle as it is locale
2032ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        // related
2033ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        structuredNameUpdate.bindLong(1, unadjustedFullNameStyle);
20345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        DatabaseUtils.bindObjectToProgram(structuredNameUpdate, 2, displayName);
20355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.bindLong(3, name.phoneticNameStyle);
20365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.bindLong(4, dataId);
20375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.execute();
20385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (displayNameSource == DisplayNameSources.STRUCTURED_NAME) {
20405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String displayNameAlternative = splitter.join(name, false);
20415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String phoneticName = splitter.joinPhoneticName(name);
20425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String sortKey = null;
20435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String sortKeyAlternative = null;
20445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            if (phoneticName != null) {
20465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKey = sortKeyAlternative = phoneticName;
2047ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao            } else if (name.fullNameStyle == FullNameStyle.CHINESE ||
2048ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                    name.fullNameStyle == FullNameStyle.CJK) {
2049ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                sortKey = sortKeyAlternative = ContactLocaleUtils.getIntance()
2050ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                        .getSortKey(displayName, name.fullNameStyle);
20515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
20525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            if (sortKey == null) {
20545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKey = displayName;
20555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKeyAlternative = displayNameAlternative;
20565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
20575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            updateRawContact205(rawContactUpdate, rawContactId, displayName,
20595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    displayNameAlternative, name.phoneticNameStyle, phoneticName, sortKey,
20605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    sortKeyAlternative);
20615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
20625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
20635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private interface Organization205Query {
20655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String TABLE = Tables.DATA_JOIN_RAW_CONTACTS;
20665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String COLUMNS[] = {
20685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.CONCRETE_ID,
20695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Data.RAW_CONTACT_ID,
20705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Organization.COMPANY,
20715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Organization.PHONETIC_NAME,
20725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        };
20735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int ID = 0;
20755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int RAW_CONTACT_ID = 1;
20765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int COMPANY = 2;
20775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_NAME = 3;
20785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
20795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeOrganizationsToVersion205(SQLiteDatabase db,
20815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement rawContactUpdate, NameSplitter splitter) {
2082b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeType = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
20835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement organizationUpdate = db.compileStatement(
20855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.DATA +
20865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
20875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        Organization.PHONETIC_NAME_STYLE + "=?" +
20885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + Data._ID + "=?");
20895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        Cursor cursor = db.query(Organization205Query.TABLE, Organization205Query.COLUMNS,
2091b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=" + mimeType + " AND "
20925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + RawContacts.DISPLAY_NAME_SOURCE + "=" + DisplayNameSources.ORGANIZATION,
20935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                null, null, null, null);
20945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
20955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            while (cursor.moveToNext()) {
20965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long dataId = cursor.getLong(Organization205Query.ID);
20975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long rawContactId = cursor.getLong(Organization205Query.RAW_CONTACT_ID);
20985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String company = cursor.getString(Organization205Query.COMPANY);
20995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String phoneticName = cursor.getString(Organization205Query.PHONETIC_NAME);
21005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
21015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                int phoneticNameStyle = splitter.guessPhoneticNameStyle(phoneticName);
21025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
21035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.bindLong(1, phoneticNameStyle);
21045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.bindLong(2, dataId);
21055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.execute();
21065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
21075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String sortKey = null;
21085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                if (phoneticName == null && company != null) {
21095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    int nameStyle = splitter.guessFullNameStyle(company);
21105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    nameStyle = splitter.getAdjustedFullNameStyle(nameStyle);
2111ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                    if (nameStyle == FullNameStyle.CHINESE ||
2112ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                            nameStyle == FullNameStyle.CJK ) {
2113ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                        sortKey = ContactLocaleUtils.getIntance()
2114ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                                .getSortKey(company, nameStyle);
21155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    }
21165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                }
21175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
21185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                if (sortKey == null) {
21195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    sortKey = company;
21205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                }
21215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
21225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                updateRawContact205(rawContactUpdate, rawContactId, company,
21235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        company, phoneticNameStyle, phoneticName, sortKey, sortKey);
21245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
21255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } finally {
21265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            cursor.close();
21275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
21285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
21295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
21305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void updateRawContact205(SQLiteStatement rawContactUpdate, long rawContactId,
21315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String displayName, String displayNameAlternative, int phoneticNameStyle,
21325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String phoneticName, String sortKeyPrimary, String sortKeyAlternative) {
21335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 1, displayName);
21345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 2, displayNameAlternative);
21355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 3, phoneticName);
21365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.bindLong(4, phoneticNameStyle);
21375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 5, sortKeyPrimary);
21385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 6, sortKeyAlternative);
21395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.bindLong(7, rawContactId);
21405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.execute();
21415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
21425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
2143f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov    private void upgrateToVersion206(SQLiteDatabase db) {
2144f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
2145f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                + " ADD " + RawContacts.NAME_VERIFIED + " INTEGER NOT NULL DEFAULT 0;");
2146f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov    }
2147f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov
214831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    private interface Organization300Query {
214931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String TABLE = Tables.DATA;
215031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
215131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String SELECTION = DataColumns.MIMETYPE_ID + "=?";
215231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
215331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String COLUMNS[] = {
215431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization._ID,
215531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.RAW_CONTACT_ID,
215631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.COMPANY,
215731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.TITLE
215831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        };
215931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
216031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int ID = 0;
216131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int RAW_CONTACT_ID = 1;
216231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int COMPANY = 2;
216331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int TITLE = 3;
216431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    }
216531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
216631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    /**
216731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     * Fix for the bug where name lookup records for organizations would get removed by
216831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     * unrelated updates of the data rows.
216931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     */
2170b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeToVersion300(SQLiteDatabase db) {
2171b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeType = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
2172b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeType == -1) {
217331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            return;
217431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
217531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
217631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        ContentValues values = new ContentValues();
217731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
217831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        // Find all data rows with the mime type "organization"
217931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        Cursor cursor = db.query(Organization300Query.TABLE, Organization300Query.COLUMNS,
2180b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Organization300Query.SELECTION, new String[] {String.valueOf(mimeType)},
218131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                null, null, null);
218231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        try {
218331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            while (cursor.moveToNext()) {
218431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                long dataId = cursor.getLong(Organization300Query.ID);
218531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                long rawContactId = cursor.getLong(Organization300Query.RAW_CONTACT_ID);
218631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                String company = cursor.getString(Organization300Query.COMPANY);
218731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                String title = cursor.getString(Organization300Query.TITLE);
218831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
218931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                // First delete name lookup if there is any (chances are there won't be)
219031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                db.delete(Tables.NAME_LOOKUP, NameLookupColumns.DATA_ID + "=?",
219131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                        new String[]{String.valueOf(dataId)});
219231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
219331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                // Now insert two name lookup records: one for company name, one for title
219431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.DATA_ID, dataId);
219531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
219631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.NAME_TYPE, NameLookupType.ORGANIZATION);
219731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
219831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                if (!TextUtils.isEmpty(company)) {
219931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME,
220031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                            NameNormalizer.normalize(company));
220131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
220231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                }
220331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
220431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                if (!TextUtils.isEmpty(title)) {
220531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME,
220631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                            NameNormalizer.normalize(title));
220731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
220831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                }
220931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            }
221031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        } finally {
221131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            cursor.close();
221231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
221331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    }
221431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
2215b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private static final class Upgrade303Query {
2216b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
2217b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2218b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String SELECTION =
2219b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=?" +
2220b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    " AND " + Data._ID + " NOT IN " +
2221b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    "(SELECT " + NameLookupColumns.DATA_ID + " FROM " + Tables.NAME_LOOKUP + ")" +
2222b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    " AND " + Data.DATA1 + " NOT NULL";
2223b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2224b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String COLUMNS[] = {
2225b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data._ID,
2226b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data.RAW_CONTACT_ID,
2227b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data.DATA1,
2228b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        };
2229b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2230b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int ID = 0;
2231b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
2232b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int DATA1 = 2;
2233b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2234b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2235b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    /**
2236b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * The {@link ContactsProvider2#update} method was deleting name lookup for new
2237b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * emails during the sync.  We need to restore the lost name lookup rows.
2238b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     */
2239b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeEmailToVersion303(SQLiteDatabase db) {
2240b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Email.CONTENT_ITEM_TYPE);
2241b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeTypeId == -1) {
2242b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return;
2243b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2244b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2245b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        ContentValues values = new ContentValues();
2246b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2247b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        // Find all data rows with the mime type "email" that are missing name lookup
2248b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Cursor cursor = db.query(Upgrade303Query.TABLE, Upgrade303Query.COLUMNS,
2249b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Upgrade303Query.SELECTION, new String[] {String.valueOf(mimeTypeId)},
2250b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                null, null, null);
2251b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2252b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            while (cursor.moveToNext()) {
2253b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long dataId = cursor.getLong(Upgrade303Query.ID);
2254b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long rawContactId = cursor.getLong(Upgrade303Query.RAW_CONTACT_ID);
2255b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                String value = cursor.getString(Upgrade303Query.DATA1);
2256b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                value = extractHandleFromEmailAddress(value);
2257b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2258b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                if (value != null) {
2259b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.DATA_ID, dataId);
2260b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
2261b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.NAME_TYPE, NameLookupType.EMAIL_BASED_NICKNAME);
2262b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME, NameNormalizer.normalize(value));
2263b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
2264b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                }
2265b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            }
2266b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } finally {
2267b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            cursor.close();
2268b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2269b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2270b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2271b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    /**
2272b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * The {@link ContactsProvider2#update} method was deleting name lookup for new
2273b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * nicknames during the sync.  We need to restore the lost name lookup rows.
2274b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     */
2275b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeNicknameToVersion303(SQLiteDatabase db) {
2276b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Nickname.CONTENT_ITEM_TYPE);
2277b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeTypeId == -1) {
2278b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return;
2279b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2280b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2281b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        ContentValues values = new ContentValues();
2282b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2283b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        // Find all data rows with the mime type "nickname" that are missing name lookup
2284b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Cursor cursor = db.query(Upgrade303Query.TABLE, Upgrade303Query.COLUMNS,
2285b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Upgrade303Query.SELECTION, new String[] {String.valueOf(mimeTypeId)},
2286b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                null, null, null);
2287b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2288b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            while (cursor.moveToNext()) {
2289b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long dataId = cursor.getLong(Upgrade303Query.ID);
2290b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long rawContactId = cursor.getLong(Upgrade303Query.RAW_CONTACT_ID);
2291b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                String value = cursor.getString(Upgrade303Query.DATA1);
2292b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2293b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.DATA_ID, dataId);
2294b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
2295b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.NAME_TYPE, NameLookupType.NICKNAME);
2296b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.NORMALIZED_NAME, NameNormalizer.normalize(value));
2297b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                db.insert(Tables.NAME_LOOKUP, null, values);
2298b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            }
2299b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } finally {
2300b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            cursor.close();
2301b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2302b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2303b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
230451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void upgradeToVersion304(SQLiteDatabase db) {
230551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        // Mimetype table requires an index on mime type
230651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS mime_type ON " + Tables.MIMETYPES + " (" +
230751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                MimetypesColumns.MIMETYPE +
230851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        ");");
230951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
231051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
231160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann    private void upgradeToVersion306(SQLiteDatabase db) {
231260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        // Fix invalid lookup that was used for Exchange contacts (it was not escaped)
231360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        // It happened when a new contact was created AND synchronized
231460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final StringBuilder lookupKeyBuilder = new StringBuilder();
231560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final SQLiteStatement updateStatement = db.compileStatement(
231660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "UPDATE contacts " +
231760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "SET lookup=? " +
231860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "WHERE _id=?");
231960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final Cursor contactIdCursor = db.rawQuery(
232060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "SELECT DISTINCT contact_id " +
232160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "FROM raw_contacts " +
232260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "WHERE deleted=0 AND account_type='com.android.exchange'",
232360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                null);
232460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        try {
232560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            while (contactIdCursor.moveToNext()) {
232660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                final long contactId = contactIdCursor.getLong(0);
232760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                lookupKeyBuilder.setLength(0);
232860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                final Cursor c = db.rawQuery(
232960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "SELECT account_type, account_name, _id, sourceid, display_name " +
233060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "FROM raw_contacts " +
233160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "WHERE contact_id=? " +
233260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "ORDER BY _id",
233360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        new String[] { String.valueOf(contactId) });
233460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                try {
233560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    while (c.moveToNext()) {
233660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        ContactLookupKey.appendToLookupKey(lookupKeyBuilder,
233760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(0),
233860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(1),
233960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getLong(2),
234060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(3),
234160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(4));
234260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    }
234360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                } finally {
234460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    c.close();
234560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                }
234660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
234760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                if (lookupKeyBuilder.length() == 0) {
234860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    updateStatement.bindNull(1);
234960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                } else {
235060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    updateStatement.bindString(1, Uri.encode(lookupKeyBuilder.toString()));
235160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                }
235260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                updateStatement.bindLong(2, contactId);
235360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
235460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                updateStatement.execute();
235560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            }
235660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        } finally {
235760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            updateStatement.close();
235860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            contactIdCursor.close();
235960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        }
236060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann    }
236160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
2362b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    private void upgradeToVersion307(SQLiteDatabase db) {
2363b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        db.execSQL("CREATE TABLE properties (" +
2364b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                "property_key TEXT PRIMARY_KEY, " +
2365b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                "property_value TEXT" +
2366b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ");");
2367b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
2368b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
2369743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov    private void upgradeToVersion308(SQLiteDatabase db) {
23704394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE accounts (" +
23714394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "account_name TEXT, " +
23724394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "account_type TEXT " +
23734394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
2374743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
23754394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO accounts " +
23764394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "SELECT DISTINCT account_name, account_type FROM raw_contacts");
2377743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov    }
2378743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
2379f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov    private void upgradeToVersion400(SQLiteDatabase db) {
2380dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        db.execSQL("ALTER TABLE " + Tables.GROUPS
2381dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + " ADD " + Groups.FAVORITES + " INTEGER NOT NULL DEFAULT 0;");
2382dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        db.execSQL("ALTER TABLE " + Tables.GROUPS
2383dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + " ADD " + Groups.AUTO_ADD + " INTEGER NOT NULL DEFAULT 0;");
2384dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana    }
2385dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana
23867da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov    private void upgradeToVersion353(SQLiteDatabase db) {
23877da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        db.execSQL("DELETE FROM contacts " +
23887da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov                "WHERE NOT EXISTS (SELECT 1 FROM raw_contacts WHERE contact_id=contacts._id)");
23897da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov    }
23907da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
239151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void rebuildNameLookup(SQLiteDatabase db) {
239251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
239351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        insertNameLookup(db);
239451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        createContactsIndexes(db);
239551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
239651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
239704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
239851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     * Regenerates all locale-sensitive data: nickname_lookup, name_lookup and sort keys.
239904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
240051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    public void setLocale(ContactsProvider2 provider, Locale locale) {
240151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        Log.i(TAG, "Switching to locale " + locale);
240204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
2403c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamilton        long start = SystemClock.uptimeMillis();
240451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
240551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.setLocale(locale);
240651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.beginTransaction();
240751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
240851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX raw_contact_sort_key1_index");
240951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX raw_contact_sort_key2_index");
241051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
241151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
241251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            loadNicknameLookupTable(db);
241351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertNameLookup(db);
241451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            rebuildSortKeys(db, provider);
241551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            createContactsIndexes(db);
241651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.setTransactionSuccessful();
241751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
241851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.endTransaction();
241951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
242051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
2421c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamilton        Log.i(TAG, "Locale change completed in " + (SystemClock.uptimeMillis() - start) + "ms");
242251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
242351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
242451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    /**
242551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     * Regenerates sort keys for all contacts.
242651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     */
242751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void rebuildSortKeys(SQLiteDatabase db, ContactsProvider2 provider) {
242851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        Cursor cursor = db.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID},
242951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                null, null, null, null, null);
243051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
243151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            while (cursor.moveToNext()) {
243251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                long rawContactId = cursor.getLong(0);
243351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                provider.updateRawContactDisplayName(db, rawContactId);
243451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            }
243551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
243651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            cursor.close();
243751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
243851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
243951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
244051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void insertNameLookup(SQLiteDatabase db) {
244104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NAME_LOOKUP);
244204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
244304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        SQLiteStatement nameLookupInsert = db.compileStatement(
244404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                "INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "("
244504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.RAW_CONTACT_ID + ","
244604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.DATA_ID + ","
244704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.NAME_TYPE + ","
244804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.NORMALIZED_NAME +
244904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                ") VALUES (?,?,?,?)");
245004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
245151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
245251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertStructuredNameLookup(db, nameLookupInsert);
245351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertOrganizationLookup(db, nameLookupInsert);
245451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertEmailLookup(db, nameLookupInsert);
245551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertNicknameLookup(db, nameLookupInsert);
245651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
245751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            nameLookupInsert.close();
245851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
245904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
246004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
246104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class StructuredNameQuery {
246204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
246304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
246404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
246504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
246604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
246704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
246804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName._ID,
246904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName.RAW_CONTACT_ID,
247004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName.DISPLAY_NAME,
247104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
247204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
247304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
247404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
247504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int DISPLAY_NAME = 2;
247604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
247704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
247804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private class StructuredNameLookupBuilder extends NameLookupBuilder {
247904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
248004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        private final SQLiteStatement mNameLookupInsert;
248104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        private final CommonNicknameCache mCommonNicknameCache;
248204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
248304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public StructuredNameLookupBuilder(NameSplitter splitter,
248404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                CommonNicknameCache commonNicknameCache, SQLiteStatement nameLookupInsert) {
248504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            super(splitter);
248604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            this.mCommonNicknameCache = commonNicknameCache;
248704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            this.mNameLookupInsert = nameLookupInsert;
248804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
248904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
249004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        @Override
249104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        protected void insertNameLookup(long rawContactId, long dataId, int lookupType,
249204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String name) {
249304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            if (!TextUtils.isEmpty(name)) {
249404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                ContactsDatabaseHelper.this.insertNormalizedNameLookup(mNameLookupInsert,
249504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        rawContactId, dataId, lookupType, name);
249604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
249704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
249804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
249904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        @Override
250004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        protected String[] getCommonNicknameClusters(String normalizedName) {
250104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return mCommonNicknameCache.getCommonNicknameClusters(normalizedName);
250204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
250304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
250404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
250504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
250604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all structured names in the database.
250704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
250804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertStructuredNameLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
2509d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov        NameSplitter nameSplitter = createNameSplitter();
2510d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov        NameLookupBuilder nameLookupBuilder = new StructuredNameLookupBuilder(nameSplitter,
251104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                new CommonNicknameCache(db), nameLookupInsert);
251204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, StructuredName.CONTENT_ITEM_TYPE);
251304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(StructuredNameQuery.TABLE, StructuredNameQuery.COLUMNS,
251404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredNameQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
251504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
251604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
251704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
251804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(StructuredNameQuery.ID);
251904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(StructuredNameQuery.RAW_CONTACT_ID);
252004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String name = cursor.getString(StructuredNameQuery.DISPLAY_NAME);
2521d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov                int fullNameStyle = nameSplitter.guessFullNameStyle(name);
252251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                fullNameStyle = nameSplitter.getAdjustedFullNameStyle(fullNameStyle);
2523d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov                nameLookupBuilder.insertNameLookup(rawContactId, dataId, name, fullNameStyle);
252404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
252504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
252604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
252704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
252804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
252904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
253004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class OrganizationQuery {
253104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
253204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
253304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
253404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
253504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
253604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
253704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization._ID,
253804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.RAW_CONTACT_ID,
253904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.COMPANY,
254004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.TITLE,
254104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
254204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
254304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
254404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
254504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int COMPANY = 2;
254604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int TITLE = 3;
254704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
254804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
254904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
255004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all organizations in the database.
255104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
255204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertOrganizationLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
255304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
255404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(OrganizationQuery.TABLE, OrganizationQuery.COLUMNS,
255504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                OrganizationQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
255604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
255704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
255804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
255904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(OrganizationQuery.ID);
256004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(OrganizationQuery.RAW_CONTACT_ID);
256104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String organization = cursor.getString(OrganizationQuery.COMPANY);
256204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String title = cursor.getString(OrganizationQuery.TITLE);
256304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
256404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.ORGANIZATION, organization);
256504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
256604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.ORGANIZATION, title);
256704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
256804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
256904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
257004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
257104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
257204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
257304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class EmailQuery {
257404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
257504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
257604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
257704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
257804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
257904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
258004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email._ID,
258104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email.RAW_CONTACT_ID,
258204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email.ADDRESS,
258304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
258404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
258504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
258604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
258704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ADDRESS = 2;
258804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
258904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
259004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
259104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all email addresses in the database.
259204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
259304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertEmailLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
259404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Email.CONTENT_ITEM_TYPE);
259504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(EmailQuery.TABLE, EmailQuery.COLUMNS,
259604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                EmailQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
259704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
259804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
259904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
260004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(EmailQuery.ID);
260104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(EmailQuery.RAW_CONTACT_ID);
260204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String address = cursor.getString(EmailQuery.ADDRESS);
260304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                address = extractHandleFromEmailAddress(address);
260404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
260504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.EMAIL_BASED_NICKNAME, address);
260604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
260704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
260804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
260904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
261004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
261104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
261204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class NicknameQuery {
261304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
261404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
261504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
261604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
261704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
261804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
261904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname._ID,
262004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname.RAW_CONTACT_ID,
262104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname.NAME,
262204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
262304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
262404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
262504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
262604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int NAME = 2;
262704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
262804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
262904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
263004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all nicknames in the database.
263104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
263204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertNicknameLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
263304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Nickname.CONTENT_ITEM_TYPE);
263404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(NicknameQuery.TABLE, NicknameQuery.COLUMNS,
263504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                NicknameQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
263604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
263704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
263804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
263904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(NicknameQuery.ID);
264004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(NicknameQuery.RAW_CONTACT_ID);
264104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String nickname = cursor.getString(NicknameQuery.NAME);
264204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
264304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.NICKNAME, nickname);
264404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
264504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
264604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
264704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
264804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
264904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
265004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
265104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts a record in the {@link Tables#NAME_LOOKUP} table.
265204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
265304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    public void insertNameLookup(SQLiteStatement stmt, long rawContactId, long dataId,
265404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            int lookupType, String name) {
265504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (TextUtils.isEmpty(name)) {
265604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return;
265704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
265804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
265904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        String normalized = NameNormalizer.normalize(name);
266004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (TextUtils.isEmpty(normalized)) {
266104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return;
266204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
266304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
266404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        insertNormalizedNameLookup(stmt, rawContactId, dataId, lookupType, normalized);
266504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
266604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
266704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertNormalizedNameLookup(SQLiteStatement stmt, long rawContactId, long dataId,
266804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            int lookupType, String normalizedName) {
266904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(1, rawContactId);
267004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(2, dataId);
267104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(3, lookupType);
267204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindString(4, normalizedName);
267304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.executeInsert();
267404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
267504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
26764394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    /**
26774394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov     * Changing the VISIBLE bit from a field on both RawContacts and Contacts to a separate table.
26784394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov     */
26794394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    private void upgradeToVersion401(SQLiteDatabase db) {
26804394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.VISIBLE_CONTACTS + " (" +
26814394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
26824394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
26834394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.VISIBLE_CONTACTS +
26844394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " SELECT " + Contacts._ID +
26854394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " FROM " + Tables.CONTACTS +
26864394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " WHERE " + Contacts.IN_VISIBLE_GROUP + "!=0");
26874394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("DROP INDEX contacts_visible_index");
26884394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    }
26894394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
2690d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    /**
2691d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov     * Introducing a new table: directories.
2692d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov     */
2693d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    private void upgradeToVersion402(SQLiteDatabase db) {
2694d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        createDirectoriesTable(db);
2695d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    }
2696d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
269797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    private void upgradeToVersion403(SQLiteDatabase db) {
269897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
269997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        createDirectoriesTable(db);
270097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
270197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("ALTER TABLE raw_contacts"
270297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + " ADD raw_contact_is_read_only INTEGER NOT NULL DEFAULT 0;");
270397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
270497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("ALTER TABLE data"
270597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + " ADD is_read_only INTEGER NOT NULL DEFAULT 0;");
270697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    }
270797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
2708892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    private void upgradeToVersion405(SQLiteDatabase db) {
2709892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS phone_lookup;");
2710892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        // Private phone numbers table used for lookup
2711892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" +
2712892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID
2713892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " INTEGER REFERENCES data(_id) NOT NULL," +
2714892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID
2715892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
2716892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL," +
2717892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL" +
2718892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2719892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2720892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" +
2721892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + "," +
2722892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
2723892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
2724892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2725892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2726892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
2727892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
2728892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
2729892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
2730892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2731892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2732892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Phone.CONTENT_ITEM_TYPE);
2733892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (mimeTypeId == -1) {
2734892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            return;
2735892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
2736892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2737892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        String mCountryIso = getCountryIso();
2738892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        Cursor cursor = db.rawQuery(
2739892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    "SELECT _id, " + Phone.RAW_CONTACT_ID + ", " + Phone.NUMBER +
2740892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    " FROM " + Tables.DATA +
2741892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId
2742892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                            + " AND " + Phone.NUMBER + " NOT NULL", null);
2743892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2744892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ContentValues phoneValues = new ContentValues();
2745892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        try {
2746892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            while (cursor.moveToNext()) {
2747892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                long dataID = cursor.getLong(0);
2748892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                long rawContactID = cursor.getLong(1);
2749892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String number = cursor.getString(2);
2750892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String numberE164 = PhoneNumberUtils.formatNumberToE164(number, mCountryIso);
2751892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String normalizedNumber = PhoneNumberUtils.normalizeNumber(number);
2752892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                if (!TextUtils.isEmpty(normalizedNumber)) {
2753892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.clear();
2754892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactID);
2755892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.DATA_ID, dataID);
2756892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber);
2757892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.MIN_MATCH,
2758892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                            PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber));
2759892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    db.insert(Tables.PHONE_LOOKUP, null, phoneValues);
2760892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2761892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    if (numberE164 != null && !numberE164.equals(normalizedNumber)) {
2762892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, numberE164);
2763892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        phoneValues.put(PhoneLookupColumns.MIN_MATCH,
2764892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                                PhoneNumberUtils.toCallerIDMinMatch(numberE164));
2765892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        db.insert(Tables.PHONE_LOOKUP, null, phoneValues);
2766892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    }
2767892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                }
2768892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
2769892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        } finally {
2770892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            cursor.close();
2771892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
2772892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    }
2773892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
27742530512f639c4979fd7371c7dd25dd67e8118124Bai Tao    private void upgradeToVersion406(SQLiteDatabase db) {
27752530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        db.execSQL("ALTER TABLE calls ADD countryiso TEXT;");
27762530512f639c4979fd7371c7dd25dd67e8118124Bai Tao    }
27772530512f639c4979fd7371c7dd25dd67e8118124Bai Tao
2778d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    private void upgradeToVersion409(SQLiteDatabase db) {
2779d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
2780d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        createDirectoriesTable(db);
2781d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    }
2782d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov
2783385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    /**
2784d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov     * Adding DEFAULT_DIRECTORY table.
2785385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     */
2786d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    private void upgradeToVersion411(SQLiteDatabase db) {
2787d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS " + Tables.DEFAULT_DIRECTORY);
2788385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DEFAULT_DIRECTORY + " (" +
2789385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
2790385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        ");");
2791385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2792385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // Process contacts without an account
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                " WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL " +
2797385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL ");
2798385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2799385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // Process accounts that don't have a default group (e.g. Exchange)
2800385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
2801385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " SELECT " + RawContacts.CONTACT_ID +
2802385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS +
2803385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE NOT EXISTS" +
2804385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " (SELECT " + Groups._ID +
2805385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "  FROM " + Tables.GROUPS +
2806385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
2807385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_NAME +
2808385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "    AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
2809385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
2810385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "    AND " + Groups.AUTO_ADD + " != 0" +
2811385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ")");
2812385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2813385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        long mimetype = lookupMimeTypeId(db, GroupMembership.CONTENT_ITEM_TYPE);
2814385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2815d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        // Process accounts that do have a default group (e.g. Google)
2816385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
2817385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " SELECT " + RawContacts.CONTACT_ID +
2818385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS +
2819385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " JOIN " + Tables.DATA +
2820385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "   ON (" + RawContactsColumns.CONCRETE_ID + "=" + Data.RAW_CONTACT_ID + ")" +
2821385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE " + DataColumns.MIMETYPE_ID + "=" + mimetype +
2822d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                " AND EXISTS" +
2823d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                " (SELECT " + Groups._ID +
2824d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "  FROM " + Tables.GROUPS +
2825d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
2826d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_NAME +
2827d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "    AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
2828d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
2829d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "    AND " + Groups.AUTO_ADD + " != 0" +
2830d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                ")");
28313d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
2832385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2833e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    private void upgradeToVersion413(SQLiteDatabase db) {
28343ea7932a47027c8629d3a301e1a16e7d2c8a298dDmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
28353ea7932a47027c8629d3a301e1a16e7d2c8a298dDmitri Plotnikov        createDirectoriesTable(db);
2836e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    }
2837e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov
2838c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov    private void upgradeToVersion415(SQLiteDatabase db) {
2839c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        db.execSQL(
2840c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "ALTER TABLE " + Tables.GROUPS +
2841c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                " ADD " + Groups.GROUP_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0");
2842c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        db.execSQL(
2843c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "UPDATE " + Tables.GROUPS +
2844c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "   SET " + Groups.GROUP_IS_READ_ONLY + "=1" +
2845c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                " WHERE " + Groups.SYSTEM_ID + " NOT NULL");
2846c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov    }
2847c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov
2848d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov    private void upgradeToVersion416(SQLiteDatabase db) {
2849d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_data_id_min_match_index ON " + Tables.PHONE_LOOKUP +
2850d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov                " (" + PhoneLookupColumns.DATA_ID + ", " + PhoneLookupColumns.MIN_MATCH + ");");
2851d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov    }
2852d97464c056e8f247e1b33dce0ea2f77eb7f6c009Dmitri Plotnikov
2853b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    public String extractHandleFromEmailAddress(String email) {
2854b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email);
2855b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (tokens.length == 0) {
2856b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return null;
2857b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2858b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2859b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        String address = tokens[0].getAddress();
2860b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        int at = address.indexOf('@');
2861b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (at != -1) {
2862b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return address.substring(0, at);
2863b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2864b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        return null;
2865b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2866b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
286708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov    public String extractAddressFromEmailAddress(String email) {
286808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email);
286908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        if (tokens.length == 0) {
287008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            return null;
287108768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        }
287208768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
287350a7c86b4b49870bd19d5270722be3f1fccaf226Dmitri Plotnikov        return tokens[0].getAddress().trim();
287408768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov    }
287508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
2876b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private long lookupMimeTypeId(SQLiteDatabase db, String mimeType) {
2877b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2878b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return DatabaseUtils.longForQuery(db,
2879b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    "SELECT " + MimetypesColumns._ID +
2880b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    " FROM " + Tables.MIMETYPES +
2881b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    " WHERE " + MimetypesColumns.MIMETYPE
2882b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                            + "='" + mimeType + "'", null);
2883b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } catch (SQLiteDoneException e) {
2884b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            // No rows of this type in the database
2885b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return -1;
2886b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2887b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2888b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
28895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void bindString(SQLiteStatement stmt, int index, String value) {
28905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (value == null) {
28915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            stmt.bindNull(index);
28925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } else {
28935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            stmt.bindString(index, value);
28945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
28955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
28965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
289778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private void bindLong(SQLiteStatement stmt, int index, Number value) {
289878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (value == null) {
289978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            stmt.bindNull(index);
290078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        } else {
290178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            stmt.bindLong(index, value.longValue());
290278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
290378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
290478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
2905a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    /**
2906f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * Adds index stats into the SQLite database to force it to always use the lookup indexes.
2907f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     */
2908f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    private void updateSqliteStats(SQLiteDatabase db) {
2909f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2910f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        // Specific stats strings are based on an actual large database after running ANALYZE
2911f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        try {
29128fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.CONTACTS,
29138fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "contacts_restricted_index", "10000 9000");
29148fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.CONTACTS,
29158fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "contacts_has_phone_index", "10000 500");
29168fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
29178fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.RAW_CONTACTS,
29188fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "raw_contacts_source_id_index", "10000 1 1 1");
29198fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.RAW_CONTACTS,
29208fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "raw_contacts_contact_id_index", "10000 2");
29218fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
29228fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
29238fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "name_lookup_raw_contact_id_index", "10000 3");
29248fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
2925916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                    "name_lookup_index", "10000 3 2 2 1");
29268fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
29278fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "sqlite_autoindex_name_lookup_1", "10000 3 2 1");
29288fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
29298fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.PHONE_LOOKUP,
29308fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "phone_lookup_index", "10000 2 2 1");
293136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            updateIndexStats(db, Tables.PHONE_LOOKUP,
293236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    "phone_lookup_min_match_index", "10000 2 2 1");
29338fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
29348fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.DATA,
29358fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "data_mimetype_data1_index", "60000 5000 2");
29368fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.DATA,
29378fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "data_raw_contact_id", "60000 10");
29388fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
29398fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.GROUPS,
29408fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "groups_source_id_index", "50 1 1 1");
29418fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
29428fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NICKNAME_LOOKUP,
29438fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "sqlite_autoindex_name_lookup_1", "500 2 1");
29448fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
2945f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        } catch (SQLException e) {
2946f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            Log.e(TAG, "Could not update index stats", e);
2947f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        }
2948f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2949f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2950f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    /**
2951f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * Stores statistics for a given index.
2952f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     *
2953f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * @param stats has the following structure: the first index is the expected size of
2954f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * the table.  The following integer(s) are the expected number of records selected with the
2955f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * index.  There should be one integer per indexed column.
2956f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     */
29575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void updateIndexStats(SQLiteDatabase db, String table, String index,
29585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String stats) {
2959f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        db.execSQL("DELETE FROM sqlite_stat1 WHERE tbl='" + table + "' AND idx='" + index + "';");
2960f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        db.execSQL("INSERT INTO sqlite_stat1 (tbl,idx,stat)"
2961f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                + " VALUES ('" + table + "','" + index + "','" + stats + "');");
2962f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2963f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2964f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    @Override
2965f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    public synchronized SQLiteDatabase getWritableDatabase() {
2966f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        SQLiteDatabase db = super.getWritableDatabase();
2967f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        if (mReopenDatabase) {
2968f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            mReopenDatabase = false;
2969f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            close();
2970f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            db = super.getWritableDatabase();
2971f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        }
2972f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        return db;
2973f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2974f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2975f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    /**
2976a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov     * Wipes all data except mime type and package lookup tables.
2977a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov     */
2978a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    public void wipeData() {
2979a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
29803d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov
298133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.ACCOUNTS + ";");
298269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " VALUES(NULL, NULL)");
298333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov
2984d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CONTACTS + ";");
29855ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.RAW_CONTACTS + ";");
2986a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.DATA + ";");
2987a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.PHONE_LOOKUP + ";");
2988a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NAME_LOOKUP + ";");
2989ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("DELETE FROM " + Tables.GROUPS + ";");
2990b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.AGGREGATION_EXCEPTIONS + ";");
2991eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        db.execSQL("DELETE FROM " + Tables.SETTINGS + ";");
2992a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.ACTIVITIES + ";");
29933d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CALLS + ";");
299472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.DIRECTORIES + ";");
299572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov
2996b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        // Note: we are not removing reference data from Tables.NICKNAME_LOOKUP
2997a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
2998b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
299904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    public NameSplitter createNameSplitter() {
300004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        return new NameSplitter(
300104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_prefixes),
300204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_last_name_prefixes),
300304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_suffixes),
300404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_conjunctions),
300504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Locale.getDefault());
300604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
300704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
3008b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3009619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey     * Return the {@link ApplicationInfo#uid} for the given package name.
3010619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey     */
3011619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    public static int getUidForPackageName(PackageManager pm, String packageName) {
3012619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        try {
3013619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            ApplicationInfo clientInfo = pm.getApplicationInfo(packageName, 0 /* no flags */);
3014619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            return clientInfo.uid;
3015619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        } catch (NameNotFoundException e) {
3016619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            throw new RuntimeException(e);
3017619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        }
3018619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
3019619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
3020619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    /**
3021b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Perform an internal string-to-integer lookup using the compiled
3022b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * {@link SQLiteStatement} provided, using the in-memory cache to speed up
3023b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups. If a mapping isn't found in cache or database, it will be
3024b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * created. All new, uncached answers are added to the cache automatically.
3025b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *
3026b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param query Compiled statement used to query for the mapping.
3027b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param insert Compiled statement used to insert a new mapping when no
3028b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *            existing one is found in cache or from query.
3029b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param value Value to find mapping for.
3030b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param cache In-memory cache of previous answers.
3031b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @return An unique integer mapping for the given value.
3032b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3033f4a3b7e523e36679b68edd2af632e26648758ff2Dmitri Plotnikov    private long getCachedId(SQLiteStatement query, SQLiteStatement insert,
3034b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String value, HashMap<String, Long> cache) {
3035b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Try an in-memory cache lookup
3036b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (cache.containsKey(value)) {
3037b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return cache.get(value);
3038b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3039b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
304036d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov        synchronized (this) {
304136d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov            long id = -1;
304236d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov            try {
304336d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov                // Try searching database for mapping
304436d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov                DatabaseUtils.bindObjectToProgram(query, 1, value);
304536d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov                id = query.simpleQueryForLong();
304636d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov            } catch (SQLiteDoneException e) {
304736d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov                // Nothing found, so try inserting new mapping
304836d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov                DatabaseUtils.bindObjectToProgram(insert, 1, value);
304936d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov                id = insert.executeInsert();
305036d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov            }
305136d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov            if (id != -1) {
305236d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov                // Cache and return the new answer
305336d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov                cache.put(value, id);
305436d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov                return id;
305536d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov            } else {
305636d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov                // Otherwise throw if no mapping found or created
305736d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov                throw new IllegalStateException("Couldn't find or create internal "
305836d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov                        + "lookup table entry for value " + value);
305936d7a981711dc856da815fbc8739ee88c0236a15Dmitri Plotnikov            }
3060b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3061b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3062b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3063b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3064ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Convert a package name into an integer, using {@link Tables#PACKAGES} for
3065b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
3066b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3067b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getPackageId(String packageName) {
306878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mPackageQuery == null) {
306978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mPackageQuery = getWritableDatabase().compileStatement(
307078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + PackagesColumns._ID +
307178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.PACKAGES +
307278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + PackagesColumns.PACKAGE + "=?");
307378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
307478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
307578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mPackageInsert == null) {
307678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mPackageInsert = getWritableDatabase().compileStatement(
307778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT INTO " + Tables.PACKAGES + "("
307878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + PackagesColumns.PACKAGE +
307978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    ") VALUES (?)");
308078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3081b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return getCachedId(mPackageQuery, mPackageInsert, packageName, mPackageCache);
3082b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3083b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3084b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3085ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Convert a mimetype into an integer, using {@link Tables#MIMETYPES} for
3086b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
3087b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3088b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getMimeTypeId(String mimetype) {
3089b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return getCachedId(mMimetypeQuery, mMimetypeInsert, mimetype, mMimetypeCache);
3090b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3091b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
30922a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForStructuredName() {
30932a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdStructuredName;
30942a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
30952a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
30962a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForOrganization() {
30972a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdOrganization;
30982a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
30992a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
31002a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForIm() {
31012a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdIm;
31022a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
31032a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
31042a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForEmail() {
31052a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdEmail;
31062a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
31072a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
3108a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov    public long getMimeTypeIdForSip() {
3109a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov        return mMimeTypeIdSip;
3110a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov    }
3111a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov
31122a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public int getDisplayNameSourceForMimeTypeId(int mimeTypeId) {
31132a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        if (mimeTypeId == mMimeTypeIdStructuredName) {
31142a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.STRUCTURED_NAME;
31152a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdEmail) {
31162a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.EMAIL;
31172a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdPhone) {
31182a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.PHONE;
31192a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdOrganization) {
31202a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.ORGANIZATION;
31212a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdNickname) {
31222a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.NICKNAME;
31232a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else {
31242a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.UNDEFINED;
31252a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        }
31262a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
31272a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
3128b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3129ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Find the mimetype for the given {@link Data#_ID}.
3130b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3131b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getDataMimeType(long dataId) {
313278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mDataMimetypeQuery == null) {
313378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mDataMimetypeQuery = getWritableDatabase().compileStatement(
313478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + MimetypesColumns.MIMETYPE +
313578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.DATA_JOIN_MIMETYPES +
313678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + Tables.DATA + "." + Data._ID + "=?");
313778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3138b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
3139b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
3140b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mDataMimetypeQuery, 1, dataId);
3141b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mDataMimetypeQuery.simpleQueryForString();
3142b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
3143b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
3144b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
3145b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
3146b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3147b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3148b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3149b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3150b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Find the mime-type for the given {@link Activities#_ID}.
3151b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3152b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getActivityMimeType(long activityId) {
315378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mActivitiesMimetypeQuery == null) {
315478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mActivitiesMimetypeQuery = getWritableDatabase().compileStatement(
315578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + MimetypesColumns.MIMETYPE +
315678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.ACTIVITIES_JOIN_MIMETYPES +
315778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + Tables.ACTIVITIES + "." + Activities._ID + "=?");
315878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3159b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
3160b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
3161b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mActivitiesMimetypeQuery, 1, activityId);
3162b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mActivitiesMimetypeQuery.simpleQueryForString();
3163b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
3164b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
3165b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
3166b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
3167b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3168b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
31696bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov
31706bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov    /**
3171d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Update {@link Contacts#IN_VISIBLE_GROUP} for all contacts.
3172ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     */
3173ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public void updateAllVisible() {
3174385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        updateCustomContactVisibility(getWritableDatabase(), "");
3175ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
3176ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
3177ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    /**
3178f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov     * Updates contact visibility and return true iff the visibility was actually changed.
3179f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov     */
3180f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    public boolean updateContactVisibleOnlyIfChanged(long contactId) {
3181f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        return updateContactVisible(contactId, true);
3182f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    }
3183f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
3184f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    /**
3185385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     * Update {@link Contacts#IN_VISIBLE_GROUP} and
3186385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     * {@link Tables#DEFAULT_DIRECTORY} for a specific contact.
3187ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     */
3188fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov    public void updateContactVisible(long contactId) {
3189f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        updateContactVisible(contactId, false);
3190f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    }
3191f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
3192f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    public boolean updateContactVisible(long contactId, boolean onlyIfChanged) {
31934394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
3194f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        updateCustomContactVisibility(db, " AND " + Contacts._ID + "=" + contactId);
3195385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3196385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        String contactIdAsString = String.valueOf(contactId);
3197385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        long mimetype = getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
3198385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3199385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // The contact will be included in the default directory if contains
3200d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        // a raw contact that is in any group or in an account that
3201385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // does not have any AUTO_ADD groups.
3202f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        boolean newVisibility = DatabaseUtils.longForQuery(db,
3203385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "SELECT EXISTS (" +
3204385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts.CONTACT_ID +
3205385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3206385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " JOIN " + Tables.DATA +
3207385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   ON (" + RawContactsColumns.CONCRETE_ID + "="
3208385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                            + Data.RAW_CONTACT_ID + ")" +
3209385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3210385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + DataColumns.MIMETYPE_ID + "=?" +
3211385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ") OR EXISTS (" +
3212385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts._ID +
3213385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3214385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3215385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND NOT EXISTS" +
3216385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        " (SELECT " + Groups._ID +
3217385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  FROM " + Tables.GROUPS +
3218385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
3219385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                                + GroupsColumns.CONCRETE_ACCOUNT_NAME +
3220385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
3221385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                                + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
3222385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  AND " + Groups.AUTO_ADD + " != 0" +
3223385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        ")" +
3224385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ") OR EXISTS (" +
3225385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts._ID +
3226385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3227385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3228385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL " +
3229385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL" +
3230385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ")",
3231385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                new String[] {
3232385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    contactIdAsString,
32336c47e208236a62c55f396116e087331e05e148f3Dmitri Plotnikov                    String.valueOf(mimetype),
3234385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    contactIdAsString,
32356c47e208236a62c55f396116e087331e05e148f3Dmitri Plotnikov                    contactIdAsString
3236f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                }) != 0;
3237385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3238f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        if (onlyIfChanged) {
3239f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov            boolean oldVisibility = isContactInDefaultDirectory(db, contactId);
3240f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov            if (oldVisibility == newVisibility) {
3241f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                return false;
3242f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov            }
3243f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        }
3244f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
3245f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        if (newVisibility) {
3246385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY + " VALUES(?)",
3247385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    new String[] { contactIdAsString });
3248385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        } else {
3249385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            db.execSQL("DELETE FROM " + Tables.DEFAULT_DIRECTORY + " WHERE " + Contacts._ID + "=?",
3250385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    new String[] { contactIdAsString });
3251385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        }
3252f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        return true;
3253f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    }
3254f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
3255f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    public boolean isContactInDefaultDirectory(SQLiteDatabase db, long contactId) {
3256f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        if (mContactInDefaultDirectoryQuery == null) {
3257f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov            mContactInDefaultDirectoryQuery = db.compileStatement(
3258f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                    "SELECT EXISTS (" +
3259f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                            "SELECT 1 FROM " + Tables.DEFAULT_DIRECTORY +
3260f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                            " WHERE " + Contacts._ID + "=?)");
3261f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        }
3262f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        mContactInDefaultDirectoryQuery.bindLong(1, contactId);
3263f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        return mContactInDefaultDirectoryQuery.simpleQueryForLong() != 0;
3264385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    }
32654394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
3266385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    private void updateCustomContactVisibility(SQLiteDatabase db, String selection) {
3267ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        final long groupMembershipMimetypeId = getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
32684394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        String[] selectionArgs = new String[]{String.valueOf(groupMembershipMimetypeId)};
32694394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
32704394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // First delete what needs to be deleted, then insert what needs to be added.
32714394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // Since flash writes are very expensive, this approach is much better than
32724394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // delete-all-insert-all.
32734394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.VISIBLE_CONTACTS +
32744394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " WHERE " + "_id NOT IN" +
32754394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        "(SELECT " + Contacts._ID +
32764394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        " FROM " + Tables.CONTACTS +
32774394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        " WHERE (" + Clauses.CONTACT_IS_VISIBLE + ")=1) " + selection,
32784394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                selectionArgs);
3279fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
32804394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.VISIBLE_CONTACTS +
32814394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " SELECT " + Contacts._ID +
32824394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " FROM " + Tables.CONTACTS +
32834394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " WHERE " + Contacts._ID +
32844394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " NOT IN " + Tables.VISIBLE_CONTACTS +
32854394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                           " AND (" + Clauses.CONTACT_IS_VISIBLE + ")=1 " + selection,
32864394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                selectionArgs);
3287ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
3288ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
3289ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    /**
3290d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Returns contact ID for the given contact or zero if it is NULL.
32916bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov     */
3292d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    public long getContactId(long rawContactId) {
329378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mContactIdQuery == null) {
329478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mContactIdQuery = getWritableDatabase().compileStatement(
329578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + RawContacts.CONTACT_ID +
329678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
329778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts._ID + "=?");
329878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
32996bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        try {
3300d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov            DatabaseUtils.bindObjectToProgram(mContactIdQuery, 1, rawContactId);
3301d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov            return mContactIdQuery.simpleQueryForLong();
33026bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        } catch (SQLiteDoneException e) {
3303a3bd0246ca3741877488bca7aadd91c79b2fd8d2Fred Quintana            // No valid mapping found, so return 0
33046bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov            return 0;
33056bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        }
33066bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov    }
330761bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov
33085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov    public int getAggregationMode(long rawContactId) {
330978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mAggregationModeQuery == null) {
331078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mAggregationModeQuery = getWritableDatabase().compileStatement(
331178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + RawContacts.AGGREGATION_MODE +
331278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
331378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts._ID + "=?");
331478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3315f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        try {
33165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov            DatabaseUtils.bindObjectToProgram(mAggregationModeQuery, 1, rawContactId);
3317f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            return (int)mAggregationModeQuery.simpleQueryForLong();
3318f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        } catch (SQLiteDoneException e) {
33196cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov            // No valid row found, so return "disabled"
33206cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov            return RawContacts.AGGREGATION_MODE_DISABLED;
3321f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3322f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3323f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
3324892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    public void buildPhoneLookupAndContactQuery(
3325892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            SQLiteQueryBuilder qb, String normalizedNumber, String numberE164) {
3326892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        String minMatch = PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber);
3327e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        StringBuilder sb = new StringBuilder();
332836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        appendPhoneLookupTables(sb, minMatch, true);
3329e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        qb.setTables(sb.toString());
3330e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
3331e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb = new StringBuilder();
3332892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        appendPhoneLookupSelection(sb, normalizedNumber, numberE164);
3333e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        qb.appendWhere(sb.toString());
3334bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    }
3335bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
3336e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    public String buildPhoneLookupAsNestedQuery(String number) {
3337e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        StringBuilder sb = new StringBuilder();
333836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        final String minMatch = PhoneNumberUtils.toCallerIDMinMatch(number);
3339e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append("(SELECT DISTINCT raw_contact_id" + " FROM ");
334036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        appendPhoneLookupTables(sb, minMatch, false);
3341e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(" WHERE ");
3342892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        appendPhoneLookupSelection(sb, number, null);
3343e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(")");
3344e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        return sb.toString();
3345e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    }
3346e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
334736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    private void appendPhoneLookupTables(StringBuilder sb, final String minMatch,
3348e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov            boolean joinContacts) {
3349e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(Tables.RAW_CONTACTS);
3350e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        if (joinContacts) {
3351fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov            sb.append(" JOIN " + getContactView() + " contacts_view"
3352fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                    + " ON (contacts_view._id = raw_contacts.contact_id)");
3353e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        }
3354892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        sb.append(", (SELECT data_id, normalized_number, length(normalized_number) as len "
3355892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " FROM phone_lookup " + " WHERE (" + Tables.PHONE_LOOKUP + "."
3356892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + PhoneLookupColumns.MIN_MATCH + " = '");
335736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        sb.append(minMatch);
335836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        sb.append("')) AS lookup, " + Tables.DATA);
3359e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    }
3360e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
3361892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    private void appendPhoneLookupSelection(StringBuilder sb, String number, String numberE164) {
3362892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        sb.append("lookup.data_id=data._id AND data.raw_contact_id=raw_contacts._id");
3363892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        boolean hasNumberE164 = !TextUtils.isEmpty(numberE164);
3364892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        boolean hasNumber = !TextUtils.isEmpty(number);
3365892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (hasNumberE164 || hasNumber) {
3366892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            sb.append(" AND ( ");
3367892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumberE164) {
3368892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" lookup.normalized_number = ");
3369892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                DatabaseUtils.appendEscapedSQLString(sb, numberE164);
3370892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3371892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumberE164 && hasNumber) {
3372892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" OR ");
3373892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3374892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumber) {
3375892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                int numberLen = number.length();
3376892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" lookup.len <= ");
3377892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(numberLen);
3378892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" AND substr(");
3379892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                DatabaseUtils.appendEscapedSQLString(sb, number);
3380892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(',');
3381892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(numberLen);
3382892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" - lookup.len + 1) = lookup.normalized_number");
3383892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3384892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            sb.append(')');
3385892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
338636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    }
338736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
338836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    public String getUseStrictPhoneNumberComparisonParameter() {
338936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        return mUseStrictPhoneNumberComparison ? "1" : "0";
3390fb362d1a5df250a49fad06db323b0d41fe0e3757Dmitri Plotnikov    }
3391bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
3392619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    /**
3393b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     * Loads common nickname mappings into the database.
3394b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     */
3395b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private void loadNicknameLookupTable(SQLiteDatabase db) {
339651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NICKNAME_LOOKUP);
339751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
339828f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar        String[] strings = mContext.getResources().getStringArray(
339928f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar                com.android.internal.R.array.common_nicknames);
3400b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        if (strings == null || strings.length == 0) {
3401b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            return;
3402b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
3403b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
3404b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        SQLiteStatement nicknameLookupInsert = db.compileStatement("INSERT INTO "
3405b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                + Tables.NICKNAME_LOOKUP + "(" + NicknameLookupColumns.NAME + ","
3406b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                + NicknameLookupColumns.CLUSTER + ") VALUES (?,?)");
3407b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
340851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
340951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            for (int clusterId = 0; clusterId < strings.length; clusterId++) {
341051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                String[] names = strings[clusterId].split(",");
341151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                for (int j = 0; j < names.length; j++) {
341251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    String name = NameNormalizer.normalize(names[j]);
341351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    try {
341451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        DatabaseUtils.bindObjectToProgram(nicknameLookupInsert, 1, name);
341551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        DatabaseUtils.bindObjectToProgram(nicknameLookupInsert, 2,
341651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                                String.valueOf(clusterId));
341751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        nicknameLookupInsert.executeInsert();
341851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    } catch (SQLiteException e) {
341951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
342051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        // Print the exception and keep going - this is not a fatal error
342151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        Log.e(TAG, "Cannot insert nickname: " + names[j], e);
342251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    }
3423b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                }
3424b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            }
342551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
342651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            nicknameLookupInsert.close();
3427b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
3428b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    }
3429b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
3430f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    public static void copyStringValue(ContentValues toValues, String toKey,
3431f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            ContentValues fromValues, String fromKey) {
3432f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        if (fromValues.containsKey(fromKey)) {
3433f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            toValues.put(toKey, fromValues.getAsString(fromKey));
3434f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3435f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3436f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
3437f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    public static void copyLongValue(ContentValues toValues, String toKey,
3438f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            ContentValues fromValues, String fromKey) {
3439f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        if (fromValues.containsKey(fromKey)) {
3440f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            long longValue;
3441f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            Object value = fromValues.get(fromKey);
3442f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            if (value instanceof Boolean) {
3443f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                if ((Boolean)value) {
3444f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                    longValue = 1;
3445f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                } else {
3446f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                    longValue = 0;
3447f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                }
34481b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov            } else if (value instanceof String) {
34491b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov                longValue = Long.parseLong((String)value);
3450f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            } else {
34511b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov                longValue = ((Number)value).longValue();
3452f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            }
3453f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            toValues.put(toKey, longValue);
3454f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3455f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3456f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
345735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    public SyncStateContentProviderHelper getSyncState() {
345835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        return mSyncState;
345935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    }
3460c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3461c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    /**
3462c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     * Delete the aggregate contact if it has no constituent raw contacts other
3463c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     * than the supplied one.
3464c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     */
3465c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    public void removeContactIfSingleton(long rawContactId) {
3466c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
3467c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3468c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        // Obtain contact ID from the supplied raw contact ID
3469c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        String contactIdFromRawContactId = "(SELECT " + RawContacts.CONTACT_ID + " FROM "
3470c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=" + rawContactId + ")";
3471c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3472c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        // Find other raw contacts in the same aggregate contact
3473c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        String otherRawContacts = "(SELECT contacts1." + RawContacts._ID + " FROM "
3474c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + Tables.RAW_CONTACTS + " contacts1 JOIN " + Tables.RAW_CONTACTS + " contacts2 ON ("
3475c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "contacts1." + RawContacts.CONTACT_ID + "=contacts2." + RawContacts.CONTACT_ID
3476c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + ") WHERE contacts1." + RawContacts._ID + "!=" + rawContactId + ""
3477c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " AND contacts2." + RawContacts._ID + "=" + rawContactId + ")";
3478c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3479c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CONTACTS
3480c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " WHERE " + Contacts._ID + "=" + contactIdFromRawContactId
3481c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " AND NOT EXISTS " + otherRawContacts + ";");
3482c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    }
34834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
34844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    /**
3485b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     * Returns the value from the {@link Tables#PROPERTIES} table.
3486b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     */
3487b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public String getProperty(String key, String defaultValue) {
3488b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        Cursor cursor = getReadableDatabase().query(Tables.PROPERTIES,
3489b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                new String[]{PropertiesColumns.PROPERTY_VALUE},
3490b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_KEY + "=?",
3491b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                new String[]{key}, null, null, null);
3492b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        String value = null;
3493b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        try {
3494b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            if (cursor.moveToFirst()) {
3495b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                value = cursor.getString(0);
3496b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            }
3497b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        } finally {
3498b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            cursor.close();
3499b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        }
3500b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3501b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        return value != null ? value : defaultValue;
3502b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
3503b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3504b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    /**
3505b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     * Stores a key-value pair in the {@link Tables#PROPERTIES} table.
3506b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     */
3507b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public void setProperty(String key, String value) {
35083d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        setProperty(getWritableDatabase(), key, value);
35093d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
35103d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
35113d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    private void setProperty(SQLiteDatabase db, String key, String value) {
3512b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ContentValues values = new ContentValues();
3513b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        values.put(PropertiesColumns.PROPERTY_KEY, key);
3514b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        values.put(PropertiesColumns.PROPERTY_VALUE, value);
35153d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        db.replace(Tables.PROPERTIES, null, values);
3516b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
3517b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3518b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    /**
35194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     * Check if {@link Binder#getCallingUid()} should be allowed access to
35204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     * {@link RawContacts#IS_RESTRICTED} data.
35214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     */
3522d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    boolean hasAccessToRestrictedData() {
35234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        final PackageManager pm = mContext.getPackageManager();
35246ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        int caller = Binder.getCallingUid();
35256ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        if (caller == 0) return true; // root can do anything
35266ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        final String[] callerPackages = pm.getPackagesForUid(caller);
35274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
35284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        // Has restricted access if caller matches any packages
35294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        for (String callerPackage : callerPackages) {
3530d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton            if (hasAccessToRestrictedData(callerPackage)) {
3531763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                return true;
3532763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar            }
3533763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        }
3534763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return false;
3535763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    }
3536763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar
3537763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    /**
3538763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     * Check if requestingPackage should be allowed access to
3539763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     * {@link RawContacts#IS_RESTRICTED} data.
3540763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     */
3541d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    boolean hasAccessToRestrictedData(String requestingPackage) {
3542d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        if (mUnrestrictedPackages != null) {
3543d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton            for (String allowedPackage : mUnrestrictedPackages) {
3544d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                if (allowedPackage.equals(requestingPackage)) {
3545d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                    return true;
3546d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                }
35474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov            }
35484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        }
35494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        return false;
35504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
35514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
35524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getDataView() {
3553d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa        return getDataView(false);
3554d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3555d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3556d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    public String getDataView(boolean requireRestrictedView) {
3557d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3558d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa                Views.DATA_ALL : Views.DATA_RESTRICTED;
35594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
35604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
35614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getRawContactView() {
3562763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return getRawContactView(false);
3563763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    }
3564763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar
3565763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    public String getRawContactView(boolean requireRestrictedView) {
3566d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3567763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                Views.RAW_CONTACTS_ALL : Views.RAW_CONTACTS_RESTRICTED;
35684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
35694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
35704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getContactView() {
3571763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return getContactView(false);
35724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
35734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
3574763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    public String getContactView(boolean requireRestrictedView) {
3575d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3576763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                Views.CONTACTS_ALL : Views.CONTACTS_RESTRICTED;
3577f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey    }
3578f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey
357989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov    public String getGroupView() {
358089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        return Views.GROUPS_ALL;
358189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov    }
358289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
3583a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getRawEntitiesView() {
3584a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return getRawEntitiesView(false);
3585a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    }
3586a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
3587a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getRawEntitiesView(boolean requireRestrictedView) {
3588a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3589a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                Views.RAW_ENTITIES : Views.RAW_ENTITIES_RESTRICTED;
3590a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    }
3591a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
3592a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getEntitiesView() {
3593a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return getEntitiesView(false);
3594d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3595d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3596a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getEntitiesView(boolean requireRestrictedView) {
3597d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3598a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                Views.ENTITIES : Views.ENTITIES_RESTRICTED;
3599d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3600d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3601ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov    /**
3602ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov     * Test if any of the columns appear in the given projection.
3603ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov     */
3604ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov    public boolean isInProjection(String[] projection, String... columns) {
360582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        if (projection == null) {
360682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            return true;
360782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        }
3608ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov
360982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        // Optimized for a single-column test
361082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        if (columns.length == 1) {
361182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            String column = columns[0];
361282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            for (String test : projection) {
361382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                if (column.equals(test)) {
361482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                    return true;
361582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                }
361682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            }
361782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        } else {
361882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            for (String test : projection) {
361982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                for (String column : columns) {
3620ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                    if (column.equals(test)) {
3621ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                        return true;
3622ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                    }
3623ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                }
3624ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov            }
3625ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov        }
3626ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov        return false;
36274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
3628fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3629fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    /**
3630fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * Returns a detailed exception message for the supplied URI.  It includes the calling
3631fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * user and calling package(s).
3632fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     */
3633fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    public String exceptionMessage(Uri uri) {
3634fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        return exceptionMessage(null, uri);
3635fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    }
3636fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3637fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    /**
3638fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * Returns a detailed exception message for the supplied URI.  It includes the calling
3639fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * user and calling package(s).
3640fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     */
3641fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    public String exceptionMessage(String message, Uri uri) {
3642fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        StringBuilder sb = new StringBuilder();
3643fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (message != null) {
3644fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(message).append("; ");
3645fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3646fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        sb.append("URI: ").append(uri);
3647fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        final PackageManager pm = mContext.getPackageManager();
3648fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        int callingUid = Binder.getCallingUid();
3649fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        sb.append(", calling user: ");
3650fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        String userName = pm.getNameForUid(callingUid);
3651fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (userName != null) {
3652fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(userName);
3653fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        } else {
3654fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(callingUid);
3655fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3656fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3657fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        final String[] callerPackages = pm.getPackagesForUid(callingUid);
3658fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (callerPackages != null && callerPackages.length > 0) {
3659fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            if (callerPackages.length == 1) {
3660fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(", calling package:");
3661fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(callerPackages[0]);
3662fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            } else {
3663fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(", calling package is one of: [");
3664fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                for (int i = 0; i < callerPackages.length; i++) {
3665fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    if (i != 0) {
3666fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                        sb.append(", ");
3667fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    }
3668fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    sb.append(callerPackages[i]);
3669fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                }
3670fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append("]");
3671fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            }
3672fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3673fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3674fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        return sb.toString();
3675fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    }
3676892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
3677892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    protected String getCountryIso() {
3678892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        CountryDetector detector =
3679892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            (CountryDetector) mContext.getSystemService(Context.COUNTRY_DETECTOR);
3680892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        return detector.detectCountry().getCountryIso();
3681892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    }
368278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
368378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void deleteStatusUpdate(long dataId) {
368478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mStatusUpdateDelete == null) {
368578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateDelete = getWritableDatabase().compileStatement(
368678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "DELETE FROM " + Tables.STATUS_UPDATES +
368778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + StatusUpdatesColumns.DATA_ID + "=?");
368878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
368978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateDelete.bindLong(1, dataId);
369078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateDelete.execute();
369178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
369278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
369378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void replaceStatusUpdate(Long dataId, long timestamp, String status, String resPackage,
369478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            Long iconResource, Integer labelResource) {
369578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mStatusUpdateReplace == null) {
369678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateReplace = getWritableDatabase().compileStatement(
369778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "("
369878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdatesColumns.DATA_ID + ", "
369978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_TIMESTAMP + ","
370078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS + ","
370178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_RES_PACKAGE + ","
370278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_ICON + ","
370378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_LABEL + ")" +
370478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " VALUES (?,?,?,?,?,?)");
370578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
370678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace.bindLong(1, dataId);
370778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace.bindLong(2, timestamp);
370878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mStatusUpdateReplace, 3, status);
370978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mStatusUpdateReplace, 4, resPackage);
371078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindLong(mStatusUpdateReplace, 5, iconResource);
371178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindLong(mStatusUpdateReplace, 6, labelResource);
371278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace.execute();
371378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
371478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
371578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void insertStatusUpdate(Long dataId, String status, String resPackage, Long iconResource,
371678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            Integer labelResource) {
371778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mStatusUpdateInsert == null) {
371878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateInsert = getWritableDatabase().compileStatement(
371978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT INTO " + Tables.STATUS_UPDATES + "("
372078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdatesColumns.DATA_ID + ", "
372178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS + ","
372278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_RES_PACKAGE + ","
372378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_ICON + ","
372478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_LABEL + ")" +
372578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " VALUES (?,?,?,?,?)");
372678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
372778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        try {
372878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateInsert.bindLong(1, dataId);
372978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateInsert, 2, status);
373078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateInsert, 3, resPackage);
373178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusUpdateInsert, 4, iconResource);
373278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusUpdateInsert, 5, labelResource);
373378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateInsert.executeInsert();
373478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        } catch (SQLiteConstraintException e) {
373578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            // The row already exists - update it
373678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            if (mStatusUpdateAutoTimestamp == null) {
373778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                mStatusUpdateAutoTimestamp = getWritableDatabase().compileStatement(
373878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        "UPDATE " + Tables.STATUS_UPDATES +
373978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?,"
374078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + StatusUpdates.STATUS + "=?" +
374178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"
374278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + " AND " + StatusUpdates.STATUS + "!=?");
374378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            }
374478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
374578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            long timestamp = System.currentTimeMillis();
374678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateAutoTimestamp.bindLong(1, timestamp);
374778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateAutoTimestamp, 2, status);
374878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateAutoTimestamp.bindLong(3, dataId);
374978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateAutoTimestamp, 4, status);
375078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateAutoTimestamp.execute();
375178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
375278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            if (mStatusAttributionUpdate == null) {
375378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                mStatusAttributionUpdate = getWritableDatabase().compileStatement(
375478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        "UPDATE " + Tables.STATUS_UPDATES +
375578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?,"
375678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + StatusUpdates.STATUS_ICON + "=?,"
375778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + StatusUpdates.STATUS_LABEL + "=?" +
375878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " WHERE " + StatusUpdatesColumns.DATA_ID + "=?");
375978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            }
376078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusAttributionUpdate, 1, resPackage);
376178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusAttributionUpdate, 2, iconResource);
376278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusAttributionUpdate, 3, labelResource);
376378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusAttributionUpdate.bindLong(4, dataId);
376478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusAttributionUpdate.execute();
376578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
376678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
376778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
376878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /**
376978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Resets the {@link RawContacts#NAME_VERIFIED} flag to 0 on all other raw
377078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * contacts in the same aggregate
377178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
377278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void resetNameVerifiedForOtherRawContacts(long rawContactId) {
377378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mResetNameVerifiedForOtherRawContacts == null) {
377478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mResetNameVerifiedForOtherRawContacts = getWritableDatabase().compileStatement(
377578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.RAW_CONTACTS +
377678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + RawContacts.NAME_VERIFIED + "=0" +
377778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=(" +
377878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            "SELECT " + RawContacts.CONTACT_ID +
377978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " FROM " + Tables.RAW_CONTACTS +
378078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " WHERE " + RawContacts._ID + "=?)" +
378178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " AND " + RawContacts._ID + "!=?");
378278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
378378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts.bindLong(1, rawContactId);
378478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts.bindLong(2, rawContactId);
378578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts.execute();
378678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
378778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
378878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void setDisplayName(long rawContactId, int displayNameSource,
378978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            String displayNamePrimary, String displayNameAlternative, String phoneticName,
379078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            int phoneticNameStyle, String sortKeyPrimary, String sortKeyAlternative) {
379178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mRawContactDisplayNameUpdate == null) {
379278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mRawContactDisplayNameUpdate = getWritableDatabase().compileStatement(
379378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.RAW_CONTACTS +
379478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " +
379578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.DISPLAY_NAME_SOURCE + "=?," +
379678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.DISPLAY_NAME_PRIMARY + "=?," +
379778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," +
379878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.PHONETIC_NAME + "=?," +
379978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.PHONETIC_NAME_STYLE + "=?," +
380078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.SORT_KEY_PRIMARY + "=?," +
380178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.SORT_KEY_ALTERNATIVE + "=?" +
380278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts._ID + "=?");
380378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
380478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate.bindLong(1, displayNameSource);
380578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 2, displayNamePrimary);
380678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 3, displayNameAlternative);
380778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 4, phoneticName);
380878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate.bindLong(5, phoneticNameStyle);
380978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 6, sortKeyPrimary);
381078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 7, sortKeyAlternative);
381178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate.bindLong(8, rawContactId);
381278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate.execute();
381378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
381478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
381578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /*
381678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Sets the given dataId record in the "data" table to primary, and resets all data records of
381778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * the same mimetype and under the same contact to not be primary.
381878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     *
381978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * @param dataId the id of the data record to be set to primary. Pass -1 to clear the primary
382078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * flag of all data items of this raw contacts
382178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
382278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) {
382378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mSetPrimaryStatement == null) {
382478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mSetPrimaryStatement = getWritableDatabase().compileStatement(
382578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.DATA +
382678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + Data.IS_PRIMARY + "=(_id=?)" +
382778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=?" +
382878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "   AND " + Data.RAW_CONTACT_ID + "=?");
382978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
383078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.bindLong(1, dataId);
383178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.bindLong(2, mimeTypeId);
383278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.bindLong(3, rawContactId);
383378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.execute();
383478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
383578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
383678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /*
383778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Clears the super primary of all data items of the given raw contact. does not touch
383878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * other raw contacts of the same joined aggregate
383978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
384078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void clearSuperPrimary(long rawContactId, long mimeTypeId) {
384178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mClearSuperPrimaryStatement == null) {
384278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mClearSuperPrimaryStatement = getWritableDatabase().compileStatement(
384378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.DATA +
384478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + Data.IS_SUPER_PRIMARY + "=0" +
384578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=?" +
384678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "   AND " + Data.RAW_CONTACT_ID + "=?");
384778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
384878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement.bindLong(1, mimeTypeId);
384978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement.bindLong(2, rawContactId);
385078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement.execute();
385178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
385278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
385378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /*
385478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Sets the given dataId record in the "data" table to "super primary", and resets all data
385578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * records of the same mimetype and under the same aggregate to not be "super primary".
385678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     *
385778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * @param dataId the id of the data record to be set to primary.
385878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
385978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) {
386078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mSetSuperPrimaryStatement == null) {
386178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mSetSuperPrimaryStatement = getWritableDatabase().compileStatement(
386278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.DATA +
386378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" +
386478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=?" +
386578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "   AND " + Data.RAW_CONTACT_ID + " IN (" +
386678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            "SELECT " + RawContacts._ID +
386778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " FROM " + Tables.RAW_CONTACTS +
386878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " WHERE " + RawContacts.CONTACT_ID + " =(" +
386978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                    "SELECT " + RawContacts.CONTACT_ID +
387078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                    " FROM " + Tables.RAW_CONTACTS +
387178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                    " WHERE " + RawContacts._ID + "=?))");
387278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
387378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.bindLong(1, dataId);
387478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.bindLong(2, mimeTypeId);
387578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.bindLong(3, rawContactId);
387678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.execute();
387778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
387878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
387978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /**
388078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Inserts a record in the {@link Tables#NAME_LOOKUP} table.
388178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
388278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) {
388378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (TextUtils.isEmpty(name)) {
388478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            return;
388578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
388678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
388778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mNameLookupInsert == null) {
388878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mNameLookupInsert = getWritableDatabase().compileStatement(
388978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "("
389078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.RAW_CONTACT_ID + ","
389178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.DATA_ID + ","
389278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.NAME_TYPE + ","
389378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.NORMALIZED_NAME
389478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    + ") VALUES (?,?,?,?)");
389578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
389678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.bindLong(1, rawContactId);
389778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.bindLong(2, dataId);
389878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.bindLong(3, lookupType);
389978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mNameLookupInsert, 4, name);
390078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.executeInsert();
390178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
390278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
390378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /**
390478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element.
390578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
390678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void deleteNameLookup(long dataId) {
390778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mNameLookupDelete == null) {
390878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mNameLookupDelete = getWritableDatabase().compileStatement(
390978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "DELETE FROM " + Tables.NAME_LOOKUP +
391078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + NameLookupColumns.DATA_ID + "=?");
391178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
391278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupDelete.bindLong(1, dataId);
391378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupDelete.execute();
391478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
3915189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov
3916e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public void insertNameLookupForOrganization(long rawContactId, long dataId, String company,
3917e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            String title) {
3918e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (!TextUtils.isEmpty(company)) {
3919e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            insertNameLookup(rawContactId, dataId,
3920e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov                    NameLookupType.ORGANIZATION, NameNormalizer.normalize(company));
3921e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3922e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (!TextUtils.isEmpty(title)) {
3923e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            insertNameLookup(rawContactId, dataId,
3924e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov                    NameLookupType.ORGANIZATION, NameNormalizer.normalize(title));
3925e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3926e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
3927e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3928e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public String insertNameLookupForEmail(long rawContactId, long dataId, String email) {
3929e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (TextUtils.isEmpty(email)) {
3930e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            return null;
3931e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3932e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3933e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        String address = extractHandleFromEmailAddress(email);
3934e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (address == null) {
3935e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            return null;
3936e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3937e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3938e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        insertNameLookup(rawContactId, dataId,
3939e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov                NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address));
3940e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        return address;
3941e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
3942e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3943e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    /**
3944e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov     * Normalizes the nickname and inserts it in the name lookup table.
3945e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov     */
3946e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) {
3947e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (TextUtils.isEmpty(nickname)) {
3948e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            return;
3949e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3950e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3951e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        insertNameLookup(rawContactId, dataId,
3952e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov                NameLookupType.NICKNAME, NameNormalizer.normalize(nickname));
3953e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
3954e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
39555df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov    public void insertNameLookupForPhoneticName(long rawContactId, long dataId, String familyName,
39565df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            String middleName, String givenName) {
39575df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        mSb.setLength(0);
39585df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (familyName != null) {
39595df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            mSb.append(familyName.trim());
39605df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
39615df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (middleName != null) {
39625df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            mSb.append(middleName.trim());
39635df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
39645df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (givenName != null) {
39655df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            mSb.append(givenName.trim());
39665df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
39675df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov
39685df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (mSb.length() > 0) {
39695df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            insertNameLookup(rawContactId, dataId, NameLookupType.NAME_COLLATION_KEY,
39705df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov                    NameNormalizer.normalize(mSb.toString()));
39715df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
39725df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov
39735df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (givenName != null) {
39745df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            // We want the phonetic given name to be used for search, but not for aggregation,
39755df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            // which is why we are using NAME_SHORTHAND rather than NAME_COLLATION_KEY
39765df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            insertNameLookup(rawContactId, dataId, NameLookupType.NAME_SHORTHAND,
39775df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov                    NameNormalizer.normalize(givenName.trim()));
39785df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
39795df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov    }
39805df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov
3981189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov    /**
3982189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov     * Performs a query and returns true if any Data item of the raw contact with the given
3983189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov     * id and mimetype is marked as super-primary
3984189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov     */
3985189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov    public boolean rawContactHasSuperPrimary(long rawContactId, long mimeTypeId) {
3986189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        final Cursor existsCursor = getReadableDatabase().rawQuery(
3987189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                "SELECT EXISTS(SELECT 1 FROM " + Tables.DATA +
3988189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                " WHERE " + Data.RAW_CONTACT_ID + "=?" +
3989189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                " AND " + DataColumns.MIMETYPE_ID + "=?" +
3990189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                " AND " + Data.IS_SUPER_PRIMARY + "<>0)",
3991189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                new String[] { String.valueOf(rawContactId), String.valueOf(mimeTypeId) });
3992189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        try {
3993189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov            if (!existsCursor.moveToFirst()) throw new IllegalStateException();
3994189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov            return existsCursor.getInt(0) != 0;
3995189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        } finally {
3996189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov            existsCursor.close();
3997189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        }
3998189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov    }
3999e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
4000e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public String getCurrentCountryIso() {
4001e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        return mCountryMonitor.getCountryIso();
4002e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
4003b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey}
4004