ContactsDatabaseHelper.java revision f266e8c568905337960b1fec5379841585af92a7
1b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey/*
2b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Copyright (C) 2009 The Android Open Source Project
3b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
4b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * you may not use this file except in compliance with the License.
6b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * You may obtain a copy of the License at
7b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
8b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
10b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Unless required by applicable law or agreed to in writing, software
11b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * See the License for the specific language governing permissions and
14b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * limitations under the License
15b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey */
16b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarpackage com.android.providers.contacts;
18b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1953214b3ed12b0ff9cb589b6559311f2ac142f2e3Bjorn Bringertimport com.android.common.content.SyncStateContentProviderHelper;
20e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
2167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
2282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.content.ContentResolver;
23619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.ContentValues;
24b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.content.Context;
25619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.ApplicationInfo;
26619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.PackageManager;
27619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
28d91272b48f97243533c6580981e12a4847b5783fJeff Hamiltonimport android.content.res.Resources;
2936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikovimport android.database.Cursor;
30b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.DatabaseUtils;
31f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikovimport android.database.SQLException;
3278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException;
33b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteDatabase;
34b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteDoneException;
35b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikovimport android.database.sqlite.SQLiteException;
36b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteOpenHelper;
37bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikovimport android.database.sqlite.SQLiteQueryBuilder;
38b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteStatement;
39892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikovimport android.location.CountryDetector;
40fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikovimport android.net.Uri;
414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikovimport android.os.Binder;
42a3bd0246ca3741877488bca7aadd91c79b2fd8d2Fred Quintanaimport android.os.Bundle;
43c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamiltonimport android.os.SystemClock;
44b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.provider.BaseColumns;
45e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.provider.CallLog.Calls;
46a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract;
47b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions;
48a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email;
49a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.GroupMembership;
502a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im;
51a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname;
52a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization;
53a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone;
54a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName;
55d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.Contacts;
563d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikovimport android.provider.ContactsContract.Contacts.Photo;
57de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.Data;
58d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.provider.ContactsContract.Directory;
595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.DisplayNameSources;
605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.FullNameStyle;
61ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.Groups;
62d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts;
63eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkeyimport android.provider.ContactsContract.Settings;
6482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates;
6567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.SocialContract.Activities;
66bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikovimport android.telephony.PhoneNumberUtils;
6736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikovimport android.text.TextUtils;
68b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikovimport android.text.util.Rfc822Token;
69b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikovimport android.text.util.Rfc822Tokenizer;
70b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.util.Log;
71b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
72b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport java.util.HashMap;
735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport java.util.Locale;
74b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
75b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey/**
76b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov * Database helper for contacts. Designed as a singleton to make sure that all
77b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov * {@link android.content.ContentProvider} users get the same reference.
78b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov * Provides handy methods for maintaining package and mime-type lookup tables.
79b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey */
80b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov/* package */ class ContactsDatabaseHelper extends SQLiteOpenHelper {
81b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    private static final String TAG = "ContactsDatabaseHelper";
82b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
8397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    /**
8494c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov     * Contacts DB version ranges:
8597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     * <pre>
8697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   0-98    Cupcake/Donut
8797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   100-199 Eclair
8897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   200-299 Eclair-MR1
8997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   300-349 Froyo
9097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   350-399 Gingerbread
9197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     *   400-499 Honeycomb
9297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     * </pre>
9397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov     */
94c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov    static final int DATABASE_VERSION = 415;
95e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
96b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private static final String DATABASE_NAME = "contacts2.db";
971f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    private static final String DATABASE_PRESENCE = "presence_db";
98b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
99b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface Tables {
100d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONTACTS = "contacts";
1015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACTS = "raw_contacts";
102ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String PACKAGES = "packages";
103ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String MIMETYPES = "mimetypes";
104b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PHONE_LOOKUP = "phone_lookup";
105a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NAME_LOOKUP = "name_lookup";
106b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        public static final String AGGREGATION_EXCEPTIONS = "agg_exceptions";
107eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        public static final String SETTINGS = "settings";
108b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA = "data";
109ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String GROUPS = "groups";
1101f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        public static final String PRESENCE = "presence";
111e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        public static final String AGGREGATED_PRESENCE = "agg_presence";
112b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String NICKNAME_LOOKUP = "nickname_lookup";
113e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        public static final String CALLS = "calls";
114a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        public static final String STATUS_UPDATES = "status_updates";
115b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        public static final String PROPERTIES = "properties";
116743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        public static final String ACCOUNTS = "accounts";
1174394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        public static final String VISIBLE_CONTACTS = "visible_contacts";
118d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        public static final String DIRECTORIES = "directories";
119385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        public static final String DEFAULT_DIRECTORY = "default_directory";
120b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
121ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String DATA_JOIN_MIMETYPES = "data "
1221b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id)";
123b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
12411944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        public static final String DATA_JOIN_RAW_CONTACTS = "data "
1258e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id)";
12611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
1275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String DATA_JOIN_MIMETYPE_RAW_CONTACTS = "data "
128c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
129c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id)";
130bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
131e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        // NOTE: This requires late binding of GroupMembership MIME-type
132e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String RAW_CONTACTS_JOIN_SETTINGS_DATA_GROUPS = "raw_contacts "
133e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN settings ON ("
134e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_name = settings.account_name AND "
135e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_type = settings.account_type) "
136e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN data ON (data.mimetype_id=? AND "
137e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "data.raw_contact_id = raw_contacts._id) "
138e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN groups ON (groups._id = data." + GroupMembership.GROUP_ROW_ID
139e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + ")";
140e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
141e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        // NOTE: This requires late binding of GroupMembership MIME-type
142e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS = "settings "
143e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN raw_contacts ON ("
144e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_name = settings.account_name AND "
145e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "raw_contacts.account_type = settings.account_type) "
146e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN data ON (data.mimetype_id=? AND "
147e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    + "data.raw_contact_id = raw_contacts._id) "
148e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
149e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
150d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS = "data "
1511b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
1521b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) "
153d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
154ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
1555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_GROUPS = "data "
1561b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
1571b03c2d019966fba89dad3678dd9f04e4e5f4802Dmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) "
15867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                + "LEFT OUTER JOIN packages ON (data.package_id = packages._id) "
1599261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "LEFT OUTER JOIN groups "
1609261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "  ON (mimetypes.mimetype='" + GroupMembership.CONTENT_ITEM_TYPE + "' "
1619261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "      AND groups._id = data." + GroupMembership.GROUP_ROW_ID + ") ";
162ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
163ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String GROUPS_JOIN_PACKAGES = "groups "
164ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN packages ON (groups.package_id = packages._id)";
165ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
166b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
167b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String ACTIVITIES = "activities";
168b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
169ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String ACTIVITIES_JOIN_MIMETYPES = "activities "
170ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (activities.mimetype_id = mimetypes._id)";
171b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
172d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String ACTIVITIES_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS =
1735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                "activities "
17467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                + "LEFT OUTER JOIN packages ON (activities.package_id = packages._id) "
175ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (activities.mimetype_id = mimetypes._id) "
1765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "LEFT OUTER JOIN raw_contacts ON (activities.author_contact_id = " +
177fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        "raw_contacts._id) "
178d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
1797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana
1805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String NAME_LOOKUP_JOIN_RAW_CONTACTS = "name_lookup "
1815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "INNER JOIN raw_contacts ON (name_lookup.raw_contact_id = raw_contacts._id)";
182b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
183b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public interface Views {
1854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String DATA_ALL = "view_data";
1864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String DATA_RESTRICTED = "view_data_restricted";
1874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
1884a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String RAW_CONTACTS_ALL = "view_raw_contacts";
1894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String RAW_CONTACTS_RESTRICTED = "view_raw_contacts_restricted";
1904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
1914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String CONTACTS_ALL = "view_contacts";
1924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        public static final String CONTACTS_RESTRICTED = "view_contacts_restricted";
19389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
194a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        public static final String ENTITIES = "view_entities";
195a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        public static final String ENTITIES_RESTRICTED = "view_entities_restricted";
196a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
197a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        public static final String RAW_ENTITIES = "view_raw_entities";
198a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        public static final String RAW_ENTITIES_RESTRICTED = "view_raw_entities_restricted";
199a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
20089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        public static final String GROUPS_ALL = "view_groups";
2014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
2024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
2031f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    public interface Clauses {
204e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String MIMETYPE_IS_GROUP_MEMBERSHIP = MimetypesColumns.CONCRETE_MIMETYPE + "='"
205e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + GroupMembership.CONTENT_ITEM_TYPE + "'";
206ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
207e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String BELONGS_TO_GROUP = DataColumns.CONCRETE_GROUP_ID + "="
208ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + GroupsColumns.CONCRETE_ID;
209ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
21068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey        final String HAVING_NO_GROUPS = "COUNT(" + DataColumns.CONCRETE_GROUP_ID + ") == 0";
2119261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana
21268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey        final String GROUP_BY_ACCOUNT_CONTACT_ID = SettingsColumns.CONCRETE_ACCOUNT_NAME + ","
21368936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey                + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "," + RawContacts.CONTACT_ID;
214e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
215e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String RAW_CONTACT_IS_LOCAL = RawContactsColumns.CONCRETE_ACCOUNT_NAME
216e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + " IS NULL AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL";
217e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
218e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String ZERO_GROUP_MEMBERSHIPS = "COUNT(" + GroupsColumns.CONCRETE_ID + ")=0";
219e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
2201a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey        final String OUTER_RAW_CONTACTS = "outer_raw_contacts";
2211a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey        final String OUTER_RAW_CONTACTS_ID = OUTER_RAW_CONTACTS + "." + RawContacts._ID;
2221a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey
223b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov        final String CONTACT_IS_VISIBLE =
224b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                "SELECT " +
2251a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey                    "MAX((SELECT (CASE WHEN " +
226b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                        "(CASE" +
227b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " WHEN " + RAW_CONTACT_IS_LOCAL +
228b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " THEN 1 " +
229b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " WHEN " + ZERO_GROUP_MEMBERSHIPS +
230b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " THEN " + Settings.UNGROUPED_VISIBLE +
231b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                            " ELSE MAX(" + Groups.GROUP_VISIBLE + ")" +
232b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                         "END)=1 THEN 1 ELSE 0 END)" +
233b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS_JOIN_SETTINGS_DATA_GROUPS +
2341a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey                " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + OUTER_RAW_CONTACTS_ID + "))" +
2351a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey                " FROM " + Tables.RAW_CONTACTS + " AS " + OUTER_RAW_CONTACTS +
236b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
237b3ce7aaa2390698c9424d17df4d2979dcd902cfdDmitri Plotnikov                " GROUP BY " + RawContacts.CONTACT_ID;
238e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
239e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        final String GROUP_HAS_ACCOUNT_AND_SOURCE_ID = Groups.SOURCE_ID + "=? AND "
240e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + Groups.ACCOUNT_NAME + "=? AND " + Groups.ACCOUNT_TYPE + "=?";
2414394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
2424394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        public static final String CONTACT_VISIBLE =
2434394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            "EXISTS (SELECT _id FROM " + Tables.VISIBLE_CONTACTS
2444394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                + " WHERE " + Tables.CONTACTS +"." + Contacts._ID
2454394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        + "=" + Tables.VISIBLE_CONTACTS +"." + Contacts._ID + ")";
2461f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    }
2471f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
248d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    public interface ContactsColumns {
2494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        /**
2504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov         * This flag is set for a contact if it has only one constituent raw contact and
2514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov         * it is restricted.
2524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov         */
25367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String SINGLE_IS_RESTRICTED = "single_is_restricted";
254ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
255a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        public static final String LAST_STATUS_UPDATE_ID = "status_update_id";
256a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov
257d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_ID = Tables.CONTACTS + "." + BaseColumns._ID;
25867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
259d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_TIMES_CONTACTED = Tables.CONTACTS + "."
260d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.TIMES_CONTACTED;
261d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_LAST_TIME_CONTACTED = Tables.CONTACTS + "."
262d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.LAST_TIME_CONTACTED;
263d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_STARRED = Tables.CONTACTS + "." + Contacts.STARRED;
264d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_CUSTOM_RINGTONE = Tables.CONTACTS + "."
265d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.CUSTOM_RINGTONE;
266d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_SEND_TO_VOICEMAIL = Tables.CONTACTS + "."
267d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.SEND_TO_VOICEMAIL;
2682d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill        public static final String CONCRETE_LOOKUP_KEY = Tables.CONTACTS + "."
2692d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill                + Contacts.LOOKUP_KEY;
270619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
271619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
2726cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov    public interface RawContactsColumns {
27333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_ID =
2745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + BaseColumns._ID;
2759261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana        public static final String CONCRETE_ACCOUNT_NAME =
2765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.ACCOUNT_NAME;
2779261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana        public static final String CONCRETE_ACCOUNT_TYPE =
2785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.ACCOUNT_TYPE;
27933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_SOURCE_ID =
2805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.SOURCE_ID;
28133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_VERSION =
2825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.VERSION;
28333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_DIRTY =
2845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.DIRTY;
28533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_DELETED =
2865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.DELETED;
2877a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC1 =
2887a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC1;
2897a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC2 =
2907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC2;
2917a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC3 =
2927a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC3;
2937a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC4 =
2947a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC4;
295c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey        public static final String CONCRETE_STARRED =
296c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey                Tables.RAW_CONTACTS + "." + RawContacts.STARRED;
297bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey        public static final String CONCRETE_IS_RESTRICTED =
298bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey                Tables.RAW_CONTACTS + "." + RawContacts.IS_RESTRICTED;
2998e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov
3005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        public static final String DISPLAY_NAME = RawContacts.DISPLAY_NAME_PRIMARY;
3015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        public static final String DISPLAY_NAME_SOURCE = RawContacts.DISPLAY_NAME_SOURCE;
3028e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov        public static final String AGGREGATION_NEEDED = "aggregation_needed";
303fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
304fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        public static final String CONCRETE_DISPLAY_NAME =
305fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Tables.RAW_CONTACTS + "." + DISPLAY_NAME;
306fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        public static final String CONCRETE_CONTACT_ID =
307fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.CONTACT_ID;
308f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        public static final String CONCRETE_NAME_VERIFIED =
309f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.NAME_VERIFIED;
310619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
311619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
312619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    public interface DataColumns {
31367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String PACKAGE_ID = "package_id";
314b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE_ID = "mimetype_id";
315ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
316ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.DATA + "." + BaseColumns._ID;
317226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_MIMETYPE_ID = Tables.DATA + "." + MIMETYPE_ID;
318d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_RAW_CONTACT_ID = Tables.DATA + "."
319d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Data.RAW_CONTACT_ID;
320ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_GROUP_ID = Tables.DATA + "."
321ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + GroupMembership.GROUP_ROW_ID;
322e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov
323e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA1 = Tables.DATA + "." + Data.DATA1;
324e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA2 = Tables.DATA + "." + Data.DATA2;
325e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA3 = Tables.DATA + "." + Data.DATA3;
326e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA4 = Tables.DATA + "." + Data.DATA4;
327e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA5 = Tables.DATA + "." + Data.DATA5;
328e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA6 = Tables.DATA + "." + Data.DATA6;
329e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA7 = Tables.DATA + "." + Data.DATA7;
330e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA8 = Tables.DATA + "." + Data.DATA8;
331e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA9 = Tables.DATA + "." + Data.DATA9;
332e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA10 = Tables.DATA + "." + Data.DATA10;
3330f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA11 = Tables.DATA + "." + Data.DATA11;
3340f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA12 = Tables.DATA + "." + Data.DATA12;
3350f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA13 = Tables.DATA + "." + Data.DATA13;
3360f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA14 = Tables.DATA + "." + Data.DATA14;
3370f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA15 = Tables.DATA + "." + Data.DATA15;
338e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_IS_PRIMARY = Tables.DATA + "." + Data.IS_PRIMARY;
339226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_PACKAGE_ID = Tables.DATA + "." + PACKAGE_ID;
340e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov    }
341e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov
3420f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    // Used only for legacy API support
3430f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    public interface ExtensionsColumns {
3440f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String NAME = Data.DATA1;
3450f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String VALUE = Data.DATA2;
3460f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    }
3470f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov
3480f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    public interface GroupMembershipColumns {
3495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = Data.RAW_CONTACT_ID;
3500f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String GROUP_ROW_ID = GroupMembership.GROUP_ROW_ID;
3510f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    }
3520f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov
353e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov    public interface PhoneColumns {
354e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String NORMALIZED_NUMBER = Data.DATA4;
355e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_NORMALIZED_NUMBER = DataColumns.CONCRETE_DATA4;
356ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
357ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
358ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface GroupsColumns {
35967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String PACKAGE_ID = "package_id";
36067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
361ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.GROUPS + "." + BaseColumns._ID;
36267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String CONCRETE_SOURCE_ID = Tables.GROUPS + "." + Groups.SOURCE_ID;
363341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey        public static final String CONCRETE_ACCOUNT_NAME = Tables.GROUPS + "." + Groups.ACCOUNT_NAME;
364341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey        public static final String CONCRETE_ACCOUNT_TYPE = Tables.GROUPS + "." + Groups.ACCOUNT_TYPE;
365341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey    }
366b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
367b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface ActivitiesColumns {
368b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PACKAGE_ID = "package_id";
369b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE_ID = "mimetype_id";
370b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
371b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
372b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface PhoneLookupColumns {
373b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
374b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA_ID = "data_id";
3755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = "raw_contact_id";
376b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String NORMALIZED_NUMBER = "normalized_number";
37736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        public static final String MIN_MATCH = "min_match";
378b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
379b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
380a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    public interface NameLookupColumns {
3815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = "raw_contact_id";
38214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        public static final String DATA_ID = "data_id";
383a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NORMALIZED_NAME = "normalized_name";
384a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NAME_TYPE = "name_type";
385a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
386a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
387a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov    public final static class NameLookupType {
3882a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NAME_EXACT = 0;
3892a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NAME_VARIANT = 1;
3902a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NAME_COLLATION_KEY = 2;
3912a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int NICKNAME = 3;
3922a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov        public static final int EMAIL_BASED_NICKNAME = 4;
393a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka        public static final int ORGANIZATION = 5;
3944cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao        public static final int NAME_SHORTHAND = 6;
395f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        public static final int NAME_CONSONANTS = 7;
396a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
397a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        // This is the highest name lookup type code plus one
3985086b63bf3de5f26f495b640e85259c0ebf5ca47Dmitri Plotnikov        public static final int TYPE_COUNT = 8;
399a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov
400a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        public static boolean isBasedOnStructuredName(int nameLookupType) {
4012a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov            return nameLookupType == NameLookupType.NAME_EXACT
4022a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov                    || nameLookupType == NameLookupType.NAME_VARIANT
4032a03d9c2bf627795963561a0f9406b23dc93fec5Dmitri Plotnikov                    || nameLookupType == NameLookupType.NAME_COLLATION_KEY;
404a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        }
405a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
406a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
407ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface PackagesColumns {
408b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
409b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PACKAGE = "package";
410226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana
411226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_ID = Tables.PACKAGES + "." + _ID;
412b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
413b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
414ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface MimetypesColumns {
415b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
416b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE = "mimetype";
417ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
418ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.MIMETYPES + "." + BaseColumns._ID;
419ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_MIMETYPE = Tables.MIMETYPES + "." + MIMETYPE;
420b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
421b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
422b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov    public interface AggregationExceptionColumns {
423b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        public static final String _ID = BaseColumns._ID;
424b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov    }
425b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
426b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    public interface NicknameLookupColumns {
427b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String NAME = "name";
428b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String CLUSTER = "cluster";
429b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    }
430b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
431e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey    public interface SettingsColumns {
432e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String CONCRETE_ACCOUNT_NAME = Tables.SETTINGS + "."
433e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + Settings.ACCOUNT_NAME;
434e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey        public static final String CONCRETE_ACCOUNT_TYPE = Tables.SETTINGS + "."
435e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                + Settings.ACCOUNT_TYPE;
436e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey    }
437e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey
4384dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov    public interface PresenceColumns {
4394dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov        String RAW_CONTACT_ID = "presence_raw_contact_id";
440bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        String CONTACT_ID = "presence_contact_id";
4414dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov    }
4424dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov
443e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov    public interface AggregatedPresenceColumns {
444e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        String CONTACT_ID = "presence_contact_id";
4453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4463296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_CONTACT_ID = Tables.AGGREGATED_PRESENCE + "." + CONTACT_ID;
447e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov    }
448e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov
449a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov    public interface StatusUpdatesColumns {
450a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        String DATA_ID = "status_update_data_id";
4513296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4523296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_DATA_ID = Tables.STATUS_UPDATES + "." + DATA_ID;
4533296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4543296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_PRESENCE = Tables.STATUS_UPDATES + "." + StatusUpdates.PRESENCE;
4553296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS = Tables.STATUS_UPDATES + "." + StatusUpdates.STATUS;
4563296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_TIMESTAMP = Tables.STATUS_UPDATES + "."
4573296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey                + StatusUpdates.STATUS_TIMESTAMP;
4583296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_RES_PACKAGE = Tables.STATUS_UPDATES + "."
4593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey                + StatusUpdates.STATUS_RES_PACKAGE;
4603296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_LABEL = Tables.STATUS_UPDATES + "." + StatusUpdates.STATUS_LABEL;
4613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_ICON = Tables.STATUS_UPDATES + "." + StatusUpdates.STATUS_ICON;
4623296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey    }
4633296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4643296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey    public interface ContactsStatusUpdatesColumns {
4653296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String ALIAS = "contacts_" + Tables.STATUS_UPDATES;
4663296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4673296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_DATA_ID = ALIAS + "." + StatusUpdatesColumns.DATA_ID;
4683296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey
4693296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_PRESENCE = ALIAS + "." + StatusUpdates.PRESENCE;
4703296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS = ALIAS + "." + StatusUpdates.STATUS;
4713296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_TIMESTAMP = ALIAS + "." + StatusUpdates.STATUS_TIMESTAMP;
4723296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_RES_PACKAGE = ALIAS + "." + StatusUpdates.STATUS_RES_PACKAGE;
4733296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_LABEL = ALIAS + "." + StatusUpdates.STATUS_LABEL;
4743296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey        String CONCRETE_STATUS_ICON = ALIAS + "." + StatusUpdates.STATUS_ICON;
475a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov    }
476a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov
477b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public interface PropertiesColumns {
478b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        String PROPERTY_KEY = "property_key";
479b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        String PROPERTY_VALUE = "property_value";
480b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
481b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
482e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    public static final class DirectoryColumns {
483e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov        public static final String TYPE_RESOURCE_NAME = "typeResourceName";
484e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    }
485e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov
4863296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey    /** In-memory cache of previously found MIME-type mappings */
487bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    private final HashMap<String, Long> mMimetypeCache = new HashMap<String, Long>();
488b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** In-memory cache of previously found package name mappings */
489bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    private final HashMap<String, Long> mPackageCache = new HashMap<String, Long>();
490b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
4912a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdEmail;
4922a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdIm;
4932a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdStructuredName;
4942a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdOrganization;
4952a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdNickname;
4962a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private long mMimeTypeIdPhone;
497b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
498b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** Compiled statements for querying and inserting mappings */
499b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mMimetypeQuery;
500b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mPackageQuery;
501d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    private SQLiteStatement mContactIdQuery;
502f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    private SQLiteStatement mAggregationModeQuery;
503b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mMimetypeInsert;
504b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mPackageInsert;
505b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mDataMimetypeQuery;
506b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mActivitiesMimetypeQuery;
507b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
50878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for setting a data record to the primary. */
50978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mSetPrimaryStatement;
51078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for setting a data record to the super primary. */
51178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mSetSuperPrimaryStatement;
51278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for clearing super primary of a single record. */
51378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mClearSuperPrimaryStatement;
51478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /** Precompiled sql statement for updating a contact display name */
51578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mRawContactDisplayNameUpdate;
51678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
51778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mNameLookupInsert;
51878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mNameLookupDelete;
51978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateAutoTimestamp;
52078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateInsert;
52178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateReplace;
52278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusAttributionUpdate;
52378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mStatusUpdateDelete;
52478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private SQLiteStatement mResetNameVerifiedForOtherRawContacts;
525f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    private SQLiteStatement mContactInDefaultDirectoryQuery;
52678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
527b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private final Context mContext;
5282a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private final boolean mDatabaseOptimizationEnabled;
52935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    private final SyncStateContentProviderHelper mSyncState;
530e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    private final CountryMonitor mCountryMonitor;
5315df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov    private StringBuilder mSb = new StringBuilder();
532f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov
533f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    private boolean mReopenDatabase = false;
534f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
535b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    private static ContactsDatabaseHelper sSingleton = null;
536b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
53736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    private boolean mUseStrictPhoneNumberComparison;
5383a6a49cfb06272e3e25f3c390a9cf4002da6e34dDaisuke Miyakawa
539d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    /**
540d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton     * List of package names with access to {@link RawContacts#IS_RESTRICTED} data.
541d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton     */
542d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    private String[] mUnrestrictedPackages;
543d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton
544f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
545b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    public static synchronized ContactsDatabaseHelper getInstance(Context context) {
546b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (sSingleton == null) {
5472a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            sSingleton = new ContactsDatabaseHelper(context, DATABASE_NAME, true);
548b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
549b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return sSingleton;
550b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
551b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
5521f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    /**
55331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov     * Private constructor, callers except unit tests should obtain an instance through
55435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana     * {@link #getInstance(android.content.Context)} instead.
5551f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey     */
556b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov    ContactsDatabaseHelper(Context context) {
5572a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        this(context, null, false);
5582a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
5592a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
5602a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private ContactsDatabaseHelper(
5612a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            Context context, String databaseName, boolean optimizationEnabled) {
5622a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        super(context, databaseName, null, DATABASE_VERSION);
5632a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mDatabaseOptimizationEnabled = optimizationEnabled;
564d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        Resources resources = context.getResources();
565619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
566b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        mContext = context;
56728b3769e3fcecae56c3fc70cbcb0f95282b9640eFred Quintana        mSyncState = new SyncStateContentProviderHelper();
568e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        mCountryMonitor = new CountryMonitor(context);
56936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        mUseStrictPhoneNumberComparison =
570d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                resources.getBoolean(
571d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                        com.android.internal.R.bool.config_use_strict_phone_number_comparation);
5720f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        int resourceId = resources.getIdentifier("unrestricted_packages", "array",
5730f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov                context.getPackageName());
5740f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        if (resourceId != 0) {
5750f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov            mUnrestrictedPackages = resources.getStringArray(resourceId);
5760f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        } else {
5770f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov            mUnrestrictedPackages = new String[0];
5780f5116227592cb8e724542c598daffa383964679Dmitri Plotnikov        }
579b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
580b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
5812a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    private void refreshDatabaseCaches(SQLiteDatabase db) {
58278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateDelete = null;
58378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace = null;
58478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateInsert = null;
58578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateAutoTimestamp = null;
58678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusAttributionUpdate = null;
58778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts = null;
58878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate = null;
58978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement = null;
59078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement = null;
59178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement = null;
59278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert = null;
59378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupDelete = null;
59478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mPackageQuery = null;
59578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mPackageInsert = null;
59678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mDataMimetypeQuery = null;
59778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mActivitiesMimetypeQuery = null;
59878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mContactIdQuery = null;
59978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mAggregationModeQuery = null;
600f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        mContactInDefaultDirectoryQuery = null;
6012a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
6022a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimetypeCache.clear();
6032a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mPackageCache.clear();
6042a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
6052a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimetypeQuery = db.compileStatement(
6062a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                "SELECT " + MimetypesColumns._ID +
6072a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                " FROM " + Tables.MIMETYPES +
6082a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                " WHERE " + MimetypesColumns.MIMETYPE + "=?");
6092a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
6102a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimetypeInsert = db.compileStatement(
6112a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                "INSERT INTO " + Tables.MIMETYPES + "("
6122a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                        + MimetypesColumns.MIMETYPE +
6132a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov                ") VALUES (?)");
6142a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
6152a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdEmail = getMimeTypeId(Email.CONTENT_ITEM_TYPE);
6162a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdIm = getMimeTypeId(Im.CONTENT_ITEM_TYPE);
6172a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdStructuredName = getMimeTypeId(StructuredName.CONTENT_ITEM_TYPE);
6182a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdOrganization = getMimeTypeId(Organization.CONTENT_ITEM_TYPE);
6192a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdNickname = getMimeTypeId(Nickname.CONTENT_ITEM_TYPE);
6202a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        mMimeTypeIdPhone = getMimeTypeId(Phone.CONTENT_ITEM_TYPE);
62178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
62278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
623b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
624b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onOpen(SQLiteDatabase db) {
6252a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        refreshDatabaseCaches(db);
62635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
62778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSyncState.onDatabaseOpened(db);
6281f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
6291f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        db.execSQL("ATTACH DATABASE ':memory:' AS " + DATABASE_PRESENCE + ";");
630e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS " + DATABASE_PRESENCE + "." + Tables.PRESENCE + " ("+
63182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.DATA_ID + " INTEGER PRIMARY KEY REFERENCES data(_id)," +
63282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.PROTOCOL + " INTEGER NOT NULL," +
63382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.CUSTOM_PROTOCOL + " TEXT," +
63482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.IM_HANDLE + " TEXT," +
63582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.IM_ACCOUNT + " TEXT," +
636a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                PresenceColumns.CONTACT_ID + " INTEGER REFERENCES contacts(_id)," +
637a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                PresenceColumns.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
63882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                StatusUpdates.PRESENCE + " INTEGER," +
639aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                StatusUpdates.CHAT_CAPABILITY + " INTEGER NOT NULL DEFAULT 0," +
64082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                "UNIQUE(" + StatusUpdates.PROTOCOL + ", " + StatusUpdates.CUSTOM_PROTOCOL
64182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                    + ", " + StatusUpdates.IM_HANDLE + ", " + StatusUpdates.IM_ACCOUNT + ")" +
6421f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        ");");
6431f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
644e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE INDEX IF NOT EXISTS " + DATABASE_PRESENCE + ".presenceIndex" + " ON "
6454dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov                + Tables.PRESENCE + " (" + PresenceColumns.RAW_CONTACT_ID + ");");
64609562b6c3a420ded0d02b9bd2290de2dbab9e304Vasu Nori        db.execSQL("CREATE INDEX IF NOT EXISTS " + DATABASE_PRESENCE + ".presenceIndex2" + " ON "
64709562b6c3a420ded0d02b9bd2290de2dbab9e304Vasu Nori                + Tables.PRESENCE + " (" + PresenceColumns.CONTACT_ID + ");");
648e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov
649e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS "
650aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + DATABASE_PRESENCE + "." + Tables.AGGREGATED_PRESENCE + " ("+
651e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov                AggregatedPresenceColumns.CONTACT_ID
652e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov                        + " INTEGER PRIMARY KEY REFERENCES contacts(_id)," +
653632248ae0053fa99b1f5b4cfaab3e55b7453fcb1Vasu Nori                StatusUpdates.PRESENCE + " INTEGER," +
654aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                StatusUpdates.CHAT_CAPABILITY + " INTEGER NOT NULL DEFAULT 0" +
655e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov        ");");
656bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
657bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
658bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_deleted"
659bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEFORE DELETE ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
660bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
661bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + "   DELETE FROM " + Tables.AGGREGATED_PRESENCE
662bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + "     WHERE " + AggregatedPresenceColumns.CONTACT_ID + " = " +
663bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        "(SELECT " + PresenceColumns.CONTACT_ID +
664bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " FROM " + Tables.PRESENCE +
665bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " WHERE " + PresenceColumns.RAW_CONTACT_ID
666bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                + "=OLD." + PresenceColumns.RAW_CONTACT_ID +
667bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                        " AND NOT EXISTS" +
668bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                "(SELECT " + PresenceColumns.RAW_CONTACT_ID +
669bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " FROM " + Tables.PRESENCE +
670bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " WHERE " + PresenceColumns.CONTACT_ID
671bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                        + "=OLD." + PresenceColumns.CONTACT_ID +
672bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                " AND " + PresenceColumns.RAW_CONTACT_ID
673bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                                        + "!=OLD." + PresenceColumns.RAW_CONTACT_ID + "));"
674bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
675bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
676aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori        final String replaceAggregatePresenceSql =
677aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                "INSERT OR REPLACE INTO " + Tables.AGGREGATED_PRESENCE + "("
678093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + AggregatedPresenceColumns.CONTACT_ID + ", "
679093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.PRESENCE + ", "
680093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.CHAT_CAPABILITY + ")"
681093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                + " SELECT "
682093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + PresenceColumns.CONTACT_ID + ","
683093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.PRESENCE + ","
684093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + StatusUpdates.CHAT_CAPABILITY
685aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " FROM " + Tables.PRESENCE
686aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori                + " WHERE "
687093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + " (ifnull(" + StatusUpdates.PRESENCE + ",0)  * 10 "
688093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                            + "+ ifnull(" + StatusUpdates.CHAT_CAPABILITY + ", 0))"
689093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + " = (SELECT "
690093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + "MAX (ifnull(" + StatusUpdates.PRESENCE + ",0)  * 10 "
691093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                                + "+ ifnull(" + StatusUpdates.CHAT_CAPABILITY + ", 0))"
692093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + " FROM " + Tables.PRESENCE
693093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                        + " WHERE " + PresenceColumns.CONTACT_ID
694093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                            + "=NEW." + PresenceColumns.CONTACT_ID
695093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                    + ")"
696093b6446d0c63b8d725324ea41369b76ace153dfDmitri Plotnikov                + " AND " + PresenceColumns.CONTACT_ID + "=NEW." + PresenceColumns.CONTACT_ID + ";";
697bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
698bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_inserted"
699bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " AFTER INSERT ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
700bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
701bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + replaceAggregatePresenceSql
702bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
703bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov
704bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + DATABASE_PRESENCE + "." + Tables.PRESENCE + "_updated"
705bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " AFTER UPDATE ON " + DATABASE_PRESENCE + "." + Tables.PRESENCE
706bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " BEGIN "
707bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + replaceAggregatePresenceSql
708bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov                + " END");
709b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
710b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
711b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
712b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onCreate(SQLiteDatabase db) {
713b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        Log.i(TAG, "Bootstrapping database");
714b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
71535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        mSyncState.createDatabase(db);
71635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
717b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // One row per group of contacts corresponding to the same person
718d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.CONTACTS + " (" +
719b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
720fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
721d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.PHOTO_ID + " INTEGER REFERENCES data(_id)," +
722d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.CUSTOM_RINGTONE + " TEXT," +
723d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," +
724d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," +
725d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.LAST_TIME_CONTACTED + " INTEGER," +
726d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.STARRED + " INTEGER NOT NULL DEFAULT 0," +
727f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov                Contacts.HAS_PHONE_NUMBER + " INTEGER NOT NULL DEFAULT 0," +
7285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                Contacts.LOOKUP_KEY + " TEXT," +
729a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                ContactsColumns.LAST_STATUS_UPDATE_ID + " INTEGER REFERENCES data(_id)," +
7304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.SINGLE_IS_RESTRICTED + " INTEGER NOT NULL DEFAULT 0" +
731b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
732b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
73354d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX contacts_has_phone_index ON " + Tables.CONTACTS + " (" +
73454d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                Contacts.HAS_PHONE_NUMBER +
73554d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
73654d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
73754d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX contacts_restricted_index ON " + Tables.CONTACTS + " (" +
73854d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                ContactsColumns.SINGLE_IS_RESTRICTED +
73954d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
74054d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
741fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_name_raw_contact_id_index ON " + Tables.CONTACTS + " (" +
742fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID +
743fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
744fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
745b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Contacts table
7465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.RAW_CONTACTS + " (" +
7476cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
7486cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.IS_RESTRICTED + " INTEGER DEFAULT 0," +
7496cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.ACCOUNT_NAME + " STRING DEFAULT NULL, " +
7506cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + " STRING DEFAULT NULL, " +
7516cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.SOURCE_ID + " TEXT," +
75297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                RawContacts.RAW_CONTACT_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
7536cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.VERSION + " INTEGER NOT NULL DEFAULT 1," +
75473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov                RawContacts.DIRTY + " INTEGER NOT NULL DEFAULT 0," +
75533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov                RawContacts.DELETED + " INTEGER NOT NULL DEFAULT 0," +
75654d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                RawContacts.CONTACT_ID + " INTEGER REFERENCES contacts(_id)," +
7576cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.AGGREGATION_MODE + " INTEGER NOT NULL DEFAULT " +
7586cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                        RawContacts.AGGREGATION_MODE_DEFAULT + "," +
7598e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov                RawContactsColumns.AGGREGATION_NEEDED + " INTEGER NOT NULL DEFAULT 1," +
7606cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.CUSTOM_RINGTONE + " TEXT," +
7616cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," +
7626cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," +
7636cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.LAST_TIME_CONTACTED + " INTEGER," +
76433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov                RawContacts.STARRED + " INTEGER NOT NULL DEFAULT 0," +
7655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_PRIMARY + " TEXT," +
7665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_ALTERNATIVE + " TEXT," +
7675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_SOURCE + " INTEGER NOT NULL DEFAULT " +
76825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov                        DisplayNameSources.UNDEFINED + "," +
7695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.PHONETIC_NAME + " TEXT," +
7705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.PHONETIC_NAME_STYLE + " TEXT," +
771de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                RawContacts.SORT_KEY_PRIMARY + " TEXT COLLATE " +
772de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                        ContactsProvider2.PHONEBOOK_COLLATOR_NAME + "," +
773de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                RawContacts.SORT_KEY_ALTERNATIVE + " TEXT COLLATE " +
774de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                        ContactsProvider2.PHONEBOOK_COLLATOR_NAME + "," +
775f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                RawContacts.NAME_VERIFIED + " INTEGER NOT NULL DEFAULT 0," +
7763cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC1 + " TEXT, " +
7773cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC2 + " TEXT, " +
7783cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC3 + " TEXT, " +
7793cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC4 + " TEXT " +
780b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
781b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
78254d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contacts_contact_id_index ON " + Tables.RAW_CONTACTS + " (" +
78354d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov                RawContacts.CONTACT_ID +
78454d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov        ");");
78554d6316486a810f45abade9d985dbb52b6cb17e2Dmitri Plotnikov
7865f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contacts_source_id_index ON " + Tables.RAW_CONTACTS + " (" +
7875f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.SOURCE_ID + ", " +
7885f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + ", " +
7895f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                RawContacts.ACCOUNT_NAME +
7905f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        ");");
7915f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov
792f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        // TODO readd the index and investigate a controlled use of it
793f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//        db.execSQL("CREATE INDEX raw_contacts_agg_index ON " + Tables.RAW_CONTACTS + " (" +
794f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//                RawContactsColumns.AGGREGATION_NEEDED +
795f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov//        ");");
7968e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov
797b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Package name mapping table
798ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PACKAGES + " (" +
799ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                PackagesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
800ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                PackagesColumns.PACKAGE + " TEXT NOT NULL" +
801b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
802b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
803ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // Mimetype mapping table
804ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.MIMETYPES + " (" +
805ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                MimetypesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
806ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                MimetypesColumns.MIMETYPE + " TEXT NOT NULL" +
807b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
808b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
80908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        // Mimetype table requires an index on mime type
81008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX mime_type ON " + Tables.MIMETYPES + " (" +
81108768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov                MimetypesColumns.MIMETYPE +
81208768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        ");");
81308768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
814b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Public generic data table
815b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.DATA + " (" +
816b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
81767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                DataColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
818b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                DataColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
81911944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                Data.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
82097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                Data.IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
821f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.IS_PRIMARY + " INTEGER NOT NULL DEFAULT 0," +
822f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.IS_SUPER_PRIMARY + " INTEGER NOT NULL DEFAULT 0," +
823f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA_VERSION + " INTEGER NOT NULL DEFAULT 0," +
824f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA1 + " TEXT," +
825f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA2 + " TEXT," +
826f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA3 + " TEXT," +
827f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA4 + " TEXT," +
828f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA5 + " TEXT," +
829f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA6 + " TEXT," +
830f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA7 + " TEXT," +
831f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA8 + " TEXT," +
832f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA9 + " TEXT," +
83367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA10 + " TEXT," +
83467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA11 + " TEXT," +
83567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA12 + " TEXT," +
83667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA13 + " TEXT," +
83767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA14 + " TEXT," +
8383cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.DATA15 + " TEXT," +
8393cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC1 + " TEXT, " +
8403cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC2 + " TEXT, " +
8413cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC3 + " TEXT, " +
8423cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC4 + " TEXT " +
843b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
844b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
84511944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        db.execSQL("CREATE INDEX data_raw_contact_id ON " + Tables.DATA + " (" +
84611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                Data.RAW_CONTACT_ID +
84711944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        ");");
84811944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
84911944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        /**
85011944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov         * For email lookup and similar queries.
85111944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov         */
852f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov        db.execSQL("CREATE INDEX data_mimetype_data1_index ON " + Tables.DATA + " (" +
85311944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "," +
854f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov                Data.DATA1 +
85511944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov        ");");
85611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov
857b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Private phone numbers table used for lookup
858b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" +
859f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.DATA_ID
860892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        + " INTEGER REFERENCES data(_id) NOT NULL," +
8615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID
8625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
86336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL," +
86436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL" +
865b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
866b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
867b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" +
868f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + "," +
869f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
870b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.DATA_ID +
871b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
872b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
87336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
87436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
87536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
87636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
87736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        ");");
87836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
879a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        // Private name/nickname table used for lookup
880a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.NAME_LOOKUP + " (" +
88114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                NameLookupColumns.DATA_ID
88214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                        + " INTEGER REFERENCES data(_id) NOT NULL," +
8835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID
8845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
88511944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                NameLookupColumns.NORMALIZED_NAME + " TEXT NOT NULL," +
88611944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                NameLookupColumns.NAME_TYPE + " INTEGER NOT NULL," +
88714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                "PRIMARY KEY ("
88814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                        + NameLookupColumns.DATA_ID + ", "
88911944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                        + NameLookupColumns.NORMALIZED_NAME + ", "
89011944a13b31aa7c98f1079697f24b3a1999ca571Dmitri Plotnikov                        + NameLookupColumns.NAME_TYPE + ")" +
891a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        ");");
892a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
89314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        db.execSQL("CREATE INDEX name_lookup_raw_contact_id_index ON " + Tables.NAME_LOOKUP + " (" +
89414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID +
89514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov        ");");
89614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov
897b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.NICKNAME_LOOKUP + " (" +
898b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + " TEXT," +
899b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.CLUSTER + " TEXT" +
900b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        ");");
901b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
902b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX nickname_lookup_index ON " + Tables.NICKNAME_LOOKUP + " (" +
903b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + ", " +
904b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.CLUSTER +
905b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        ");");
906b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
907ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // Groups table
908ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.GROUPS + " (" +
909ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
91067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                GroupsColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
911035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana                Groups.ACCOUNT_NAME + " STRING DEFAULT NULL, " +
912035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana                Groups.ACCOUNT_TYPE + " STRING DEFAULT NULL, " +
913ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups.SOURCE_ID + " TEXT," +
9149261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                Groups.VERSION + " INTEGER NOT NULL DEFAULT 1," +
91573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov                Groups.DIRTY + " INTEGER NOT NULL DEFAULT 0," +
916ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups.TITLE + " TEXT," +
91767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Groups.TITLE_RES + " INTEGER," +
9180f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov                Groups.NOTES + " TEXT," +
9190f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov                Groups.SYSTEM_ID + " TEXT," +
92094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana                Groups.DELETED + " INTEGER NOT NULL DEFAULT 0," +
921eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Groups.GROUP_VISIBLE + " INTEGER NOT NULL DEFAULT 0," +
922ea547d55f864133861b2db44221ae0c2ac6c1a68Fred Quintana                Groups.SHOULD_SYNC + " INTEGER NOT NULL DEFAULT 1," +
923dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                Groups.AUTO_ADD + " INTEGER NOT NULL DEFAULT 0," +
924dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                Groups.FAVORITES + " INTEGER NOT NULL DEFAULT 0," +
925c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                Groups.GROUP_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0," +
9263cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC1 + " TEXT, " +
9273cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC2 + " TEXT, " +
9283cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC3 + " TEXT, " +
9293cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC4 + " TEXT " +
930ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        ");");
931ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
9325f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        db.execSQL("CREATE INDEX groups_source_id_index ON " + Tables.GROUPS + " (" +
9335f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.SOURCE_ID + ", " +
9345f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.ACCOUNT_TYPE + ", " +
9355f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov                Groups.ACCOUNT_NAME +
9365f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov        ");");
9375f515d93c04729e6cdc9b704d18579162d71d5f2Dmitri Plotnikov
938b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.AGGREGATION_EXCEPTIONS + " (" +
939b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                AggregationExceptionColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
940b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                AggregationExceptions.TYPE + " INTEGER NOT NULL, " +
9410c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1
9425ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id), " +
9430c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2
9445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id)" +
945b0160a0bcf6d59eaa43fd501e124b95f873e0157Marc Blank        ");");
946b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
947b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index1 ON " +
948b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                Tables.AGGREGATION_EXCEPTIONS + " (" +
9490c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1 + ", " +
9500c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2 +
951b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        ");");
952b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
953b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index2 ON " +
954b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                Tables.AGGREGATION_EXCEPTIONS + " (" +
9550c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID2 + ", " +
9560c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov                AggregationExceptions.RAW_CONTACT_ID1 +
957b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        ");");
958b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
959eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.SETTINGS + " (" +
960eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.ACCOUNT_NAME + " STRING NOT NULL," +
961eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.ACCOUNT_TYPE + " STRING NOT NULL," +
962eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.UNGROUPED_VISIBLE + " INTEGER NOT NULL DEFAULT 0," +
963eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                Settings.SHOULD_SYNC + " INTEGER NOT NULL DEFAULT 1, " +
964eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey                "PRIMARY KEY (" + Settings.ACCOUNT_NAME + ", " +
965e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey                    Settings.ACCOUNT_TYPE + ") ON CONFLICT REPLACE" +
966eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        ");");
967eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey
9684394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.VISIBLE_CONTACTS + " (" +
9694394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
9704394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
9714394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
972385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DEFAULT_DIRECTORY + " (" +
973385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
974385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        ");");
975385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
976e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        // The table for recent calls is here so we can do table joins
977e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        // on people, phones, and calls all in one place.
978e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.CALLS + " (" +
979e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
980e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.NUMBER + " TEXT," +
981e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.DATE + " INTEGER," +
982e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.DURATION + " INTEGER," +
983e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.TYPE + " INTEGER," +
984e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.NEW + " INTEGER," +
985e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NAME + " TEXT," +
986e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NUMBER_TYPE + " INTEGER," +
9872530512f639c4979fd7371c7dd25dd67e8118124Bai Tao                Calls.CACHED_NUMBER_LABEL + " TEXT," +
9882530512f639c4979fd7371c7dd25dd67e8118124Bai Tao                Calls.COUNTRY_ISO + " TEXT" + ");");
989e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov
990b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Activities table
991b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.ACTIVITIES + " (" +
992b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
99367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                ActivitiesColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
994b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                ActivitiesColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
995b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.RAW_ID + " TEXT," +
996499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.IN_REPLY_TO + " TEXT," +
9975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Activities.AUTHOR_CONTACT_ID +  " INTEGER REFERENCES raw_contacts(_id)," +
9985ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Activities.TARGET_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
999b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.PUBLISHED + " INTEGER NOT NULL," +
1000499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.THREAD_PUBLISHED + " INTEGER NOT NULL," +
1001b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.TITLE + " TEXT NOT NULL," +
1002b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.SUMMARY + " TEXT," +
1003adb55c2d8295d300961d86a3605c8ddc469cd4a2Dmitri Plotnikov                Activities.LINK + " TEXT, " +
1004b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.THUMBNAIL + " BLOB" +
1005b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
1006b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1007a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.STATUS_UPDATES + " (" +
1008a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov                StatusUpdatesColumns.DATA_ID + " INTEGER PRIMARY KEY REFERENCES data(_id)," +
10090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS + " TEXT," +
10100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_TIMESTAMP + " INTEGER," +
10110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_RES_PACKAGE + " TEXT, " +
10120a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_LABEL + " INTEGER, " +
10130a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov                StatusUpdates.STATUS_ICON + " INTEGER" +
1014a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov        ");");
1015a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov
1016b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.PROPERTIES + " (" +
1017b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_KEY + " TEXT PRIMARY KEY, " +
1018b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_VALUE + " TEXT " +
1019b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ");");
1020b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
1021743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.ACCOUNTS + " (" +
1022743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov                RawContacts.ACCOUNT_NAME + " TEXT, " +
1023743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + " TEXT " +
1024743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        ");");
1025743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
1026743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // Allow contacts without any account to be created for now.  Achieve that
1027743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // by inserting a fake account with both type and name as NULL.
1028743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // This "account" should be eliminated as soon as the first real writable account
1029743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        // is added to the phone.
1030743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        db.execSQL("INSERT INTO accounts VALUES(NULL, NULL)");
1031743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
1032d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        createDirectoriesTable(db);
1033d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
1034a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        createContactsViews(db);
1035a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        createGroupsView(db);
1036fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        createContactsTriggers(db);
1037916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        createContactsIndexes(db);
10384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
1039a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        loadNicknameLookupTable(db);
1040a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1041a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        // Add the legacy API support views, etc
1042a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        LegacyApiSupport.createDatabase(db);
1043a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
10442a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        if (mDatabaseOptimizationEnabled) {
10452a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // This will create a sqlite_stat1 table that is used for query optimization
10462a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            db.execSQL("ANALYZE;");
1047a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
10482a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            updateSqliteStats(db);
1049a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
10502a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // We need to close and reopen the database connection so that the stats are
10512a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // taken into account. Make a note of it and do the actual reopening in the
10522a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            // getWritableDatabase method.
10532a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            mReopenDatabase = true;
10542a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        }
1055a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1056a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        ContentResolver.requestSync(null /* all accounts */,
1057a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                ContactsContract.AUTHORITY, new Bundle());
1058a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    }
1059a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1060d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    private void createDirectoriesTable(SQLiteDatabase db) {
1061d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DIRECTORIES + "(" +
1062d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
1063d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.PACKAGE_NAME + " TEXT NOT NULL," +
1064d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.DIRECTORY_AUTHORITY + " TEXT NOT NULL," +
1065d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.TYPE_RESOURCE_ID + " INTEGER," +
1066e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov                DirectoryColumns.TYPE_RESOURCE_NAME + " TEXT," +
1067d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.ACCOUNT_TYPE + " TEXT," +
1068d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.ACCOUNT_NAME + " TEXT," +
1069d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.DISPLAY_NAME + " TEXT, " +
1070d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov                Directory.EXPORT_SUPPORT + " INTEGER NOT NULL" +
107197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                        " DEFAULT " + Directory.EXPORT_SUPPORT_NONE + "," +
107297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                Directory.SHORTCUT_SUPPORT + " INTEGER NOT NULL" +
10733d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        " DEFAULT " + Directory.SHORTCUT_SUPPORT_NONE + "," +
10743d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                Directory.PHOTO_SUPPORT + " INTEGER NOT NULL" +
10753d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        " DEFAULT " + Directory.PHOTO_SUPPORT_NONE +
1076d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        ");");
1077d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
10783d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        // Trigger a full scan of directories in the system
10793d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        setProperty(db, ContactDirectoryManager.PROPERTY_DIRECTORY_SCAN_COMPLETE, "0");
1080d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    }
1081d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
1082916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    private static void createContactsTriggers(SQLiteDatabase db) {
1083fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1084fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        /*
1085fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * Automatically delete Data rows when a raw contact is deleted.
1086fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         */
1087fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.RAW_CONTACTS + "_deleted;");
1088fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_deleted "
1089fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   BEFORE DELETE ON " + Tables.RAW_CONTACTS
1090fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1091fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.DATA
1092fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Data.RAW_CONTACT_ID
1093fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID + ";"
1094fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.AGGREGATION_EXCEPTIONS
1095fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + AggregationExceptions.RAW_CONTACT_ID1
1096fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID
1097fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "        OR " + AggregationExceptions.RAW_CONTACT_ID2
1098fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                                + "=OLD." + RawContacts._ID + ";"
109935da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "   DELETE FROM " + Tables.VISIBLE_CONTACTS
110035da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
110135da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
110235da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
110335da06eb902047d8f3eb1698450d7bfdc41f22d4Dmitri Plotnikov                + "           )=1;"
1104385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "   DELETE FROM " + Tables.DEFAULT_DIRECTORY
1105385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
1106385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
1107385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
1108385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                + "           )=1;"
1109fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.CONTACTS
1110fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Contacts._ID + "=OLD." + RawContacts.CONTACT_ID
1111fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "       AND (SELECT COUNT(*) FROM " + Tables.RAW_CONTACTS
1112fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "            WHERE " + RawContacts.CONTACT_ID + "=OLD." + RawContacts.CONTACT_ID
1113fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "           )=1;"
1114fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1115fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1116fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1117fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS contacts_times_contacted;");
11186c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        db.execSQL("DROP TRIGGER IF EXISTS raw_contacts_times_contacted;");
1119fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1120fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        /*
1121fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * Triggers that update {@link RawContacts#VERSION} when the contact is
1122fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * marked for deletion or any time a data row is inserted, updated or
1123fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         * deleted.
1124fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov         */
1125fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.RAW_CONTACTS + "_marked_deleted;");
1126fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_marked_deleted "
11277f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori                + "   AFTER UPDATE ON " + Tables.RAW_CONTACTS
1128fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1129fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1130fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET "
1131fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                +         RawContacts.VERSION + "=OLD." + RawContacts.VERSION + "+1 "
1132fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + RawContacts._ID
1133fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "       AND NEW." + RawContacts.DELETED + "!= OLD." + RawContacts.DELETED + ";"
1134fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1135fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1136fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.DATA + "_updated;");
11377f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_updated AFTER UPDATE ON " + Tables.DATA
1138fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1139fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.DATA
1140fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + Data.DATA_VERSION + "=OLD." + Data.DATA_VERSION + "+1 "
1141fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Data._ID + "=OLD." + Data._ID + ";"
1142fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1143fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + RawContacts.VERSION + "=" + RawContacts.VERSION + "+1 "
1144fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + Data.RAW_CONTACT_ID + ";"
1145fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1146fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1147fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.DATA + "_deleted;");
1148fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_deleted BEFORE DELETE ON " + Tables.DATA
1149fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1150fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
1151fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET " + RawContacts.VERSION + "=" + RawContacts.VERSION + "+1 "
1152fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + Data.RAW_CONTACT_ID + ";"
1153fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.PHONE_LOOKUP
1154fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + PhoneLookupColumns.DATA_ID + "=OLD." + Data._ID + ";"
1155fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.STATUS_UPDATES
1156fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + StatusUpdatesColumns.DATA_ID + "=OLD." + Data._ID + ";"
1157fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   DELETE FROM " + Tables.NAME_LOOKUP
1158fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + NameLookupColumns.DATA_ID + "=OLD." + Data._ID + ";"
1159fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1160fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1161fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1162fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("DROP TRIGGER IF EXISTS " + Tables.GROUPS + "_updated1;");
1163fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.GROUPS + "_updated1 "
11647f61664c2b587e27f52edcb9a8b91986154ec637Vasu Nori                + "   AFTER UPDATE ON " + Tables.GROUPS
1165fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " BEGIN "
1166fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "   UPDATE " + Tables.GROUPS
1167fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     SET "
1168fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                +         Groups.VERSION + "=OLD." + Groups.VERSION + "+1"
1169fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + "     WHERE " + Groups._ID + "=OLD." + Groups._ID + ";"
1170fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov                + " END");
1171fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov    }
1172fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
1173916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    private static void createContactsIndexes(SQLiteDatabase db) {
1174916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
1175916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        db.execSQL("CREATE INDEX name_lookup_index ON " + Tables.NAME_LOOKUP + " (" +
1176916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.NORMALIZED_NAME + "," +
1177916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.NAME_TYPE + ", " +
1178916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID + ", " +
1179916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                NameLookupColumns.DATA_ID +
1180916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        ");");
118104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
118204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS raw_contact_sort_key1_index");
118304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
118404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                RawContacts.SORT_KEY_PRIMARY +
118504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        ");");
118604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
118704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS raw_contact_sort_key2_index");
118804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key2_index ON " + Tables.RAW_CONTACTS + " (" +
118904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                RawContacts.SORT_KEY_ALTERNATIVE +
119004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        ");");
1191916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov    }
1192916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov
1193a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    private static void createContactsViews(SQLiteDatabase db) {
1194a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.CONTACTS_ALL + ";");
1195a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.CONTACTS_RESTRICTED + ";");
1196a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.DATA_ALL + ";");
1197a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.DATA_RESTRICTED + ";");
1198a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_CONTACTS_ALL + ";");
1199a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_CONTACTS_RESTRICTED + ";");
1200a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_ENTITIES + ";");
1201a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_ENTITIES_RESTRICTED + ";");
1202a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.ENTITIES + ";");
1203a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.ENTITIES_RESTRICTED + ";");
1204a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
12054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String dataColumns =
12064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                Data.IS_PRIMARY + ", "
12074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.IS_SUPER_PRIMARY + ", "
12084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA_VERSION + ", "
12094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + PackagesColumns.PACKAGE + " AS " + Data.RES_PACKAGE + ","
12104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + MimetypesColumns.MIMETYPE + " AS " + Data.MIMETYPE + ", "
121197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + Data.IS_READ_ONLY + ", "
12124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA1 + ", "
12134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA2 + ", "
12144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA3 + ", "
12154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA4 + ", "
12164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA5 + ", "
12174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA6 + ", "
12184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA7 + ", "
12194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA8 + ", "
12204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA9 + ", "
12214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA10 + ", "
12224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA11 + ", "
12234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA12 + ", "
12244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA13 + ", "
12254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA14 + ", "
12264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.DATA15 + ", "
12274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC1 + ", "
12284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC2 + ", "
12294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC3 + ", "
12304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.SYNC4;
12314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String syncColumns =
12334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AS " + RawContacts.ACCOUNT_NAME + ","
12344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AS " + RawContacts.ACCOUNT_TYPE + ","
12354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SOURCE_ID + " AS " + RawContacts.SOURCE_ID + ","
1236f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                + RawContactsColumns.CONCRETE_NAME_VERIFIED + " AS " + RawContacts.NAME_VERIFIED + ","
12374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_VERSION + " AS " + RawContacts.VERSION + ","
12384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DIRTY + " AS " + RawContacts.DIRTY + ","
12394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC1 + " AS " + RawContacts.SYNC1 + ","
12404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC2 + " AS " + RawContacts.SYNC2 + ","
12414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC3 + " AS " + RawContacts.SYNC3 + ","
12424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_SYNC4 + " AS " + RawContacts.SYNC4;
12434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12443d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        String baseContactColumns =
12453d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                Contacts.HAS_PHONE_NUMBER + ", "
12463d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.NAME_RAW_CONTACT_ID + ", "
12473d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.LOOKUP_KEY + ", "
12483d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Contacts.PHOTO_ID + ", "
12493d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + Clauses.CONTACT_VISIBLE + " AS " + Contacts.IN_VISIBLE_GROUP + ", "
12503d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + ContactsColumns.LAST_STATUS_UPDATE_ID;
12513d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
12524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactOptionColumns =
12534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.CONCRETE_CUSTOM_RINGTONE
12544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.CUSTOM_RINGTONE + ","
12554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL
12564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.SEND_TO_VOICEMAIL + ","
12574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_LAST_TIME_CONTACTED
12584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.LAST_TIME_CONTACTED + ","
12594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_TIMES_CONTACTED
12604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.TIMES_CONTACTED + ","
12614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_STARRED
12624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + RawContacts.STARRED;
12634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
12645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String contactNameColumns =
12655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "name_raw_contact." + RawContacts.DISPLAY_NAME_SOURCE
12665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_SOURCE + ", "
12675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.DISPLAY_NAME_PRIMARY
12685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_PRIMARY + ", "
12695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.DISPLAY_NAME_ALTERNATIVE
12705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.DISPLAY_NAME_ALTERNATIVE + ", "
12715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.PHONETIC_NAME
12725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.PHONETIC_NAME + ", "
12735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.PHONETIC_NAME_STYLE
12745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.PHONETIC_NAME_STYLE + ", "
12755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.SORT_KEY_PRIMARY
12765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + " AS " + Contacts.SORT_KEY_PRIMARY + ", "
12775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + "name_raw_contact." + RawContacts.SORT_KEY_ALTERNATIVE
12784394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        + " AS " + Contacts.SORT_KEY_ALTERNATIVE;
12795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
12804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String dataSelect = "SELECT "
12814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + Data._ID + ","
12824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Data.RAW_CONTACT_ID + ", "
1283fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + RawContacts.CONTACT_ID + ", "
12844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + syncColumns + ", "
12854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + dataColumns + ", "
12864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + contactOptionColumns + ", "
12875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + contactNameColumns + ", "
12883d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + baseContactColumns + ", "
12893d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
12903d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_URI) + ", "
12913d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
12923d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_THUMBNAIL_URI) + ", "
12934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
12944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.DATA
1295a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.MIMETYPES + " ON ("
12964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1297a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " ON ("
12984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1299a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " JOIN " + Tables.CONTACTS + " ON ("
1300fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   RawContactsColumns.CONCRETE_CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID + ")"
1301fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1302fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")"
1303a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1304a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
13054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
13064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1307f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1308a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                        + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
13094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.DATA_ALL + " AS " + dataSelect);
13114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.DATA_RESTRICTED + " AS " + dataSelect + " WHERE "
1312fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0");
13134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String rawContactOptionColumns =
13154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                RawContacts.CUSTOM_RINGTONE + ","
13164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.SEND_TO_VOICEMAIL + ","
13174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.LAST_TIME_CONTACTED + ","
13184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.TIMES_CONTACTED + ","
13194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.STARRED;
13204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String rawContactsSelect = "SELECT "
13224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + RawContacts._ID + ","
13234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.CONTACT_ID + ", "
13244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.AGGREGATION_MODE + ", "
132597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + RawContacts.RAW_CONTACT_IS_READ_ONLY + ", "
13264a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + RawContacts.DELETED + ", "
13275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_SOURCE  + ", "
13285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_PRIMARY  + ", "
13295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.DISPLAY_NAME_ALTERNATIVE  + ", "
13305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.PHONETIC_NAME  + ", "
13315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.PHONETIC_NAME_STYLE  + ", "
13325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.SORT_KEY_PRIMARY  + ", "
13335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + RawContacts.SORT_KEY_ALTERNATIVE + ", "
13344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + rawContactOptionColumns + ", "
13354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + syncColumns
13364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS;
13374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_CONTACTS_ALL + " AS " + rawContactsSelect);
13394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_CONTACTS_RESTRICTED + " AS " + rawContactsSelect
13404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " WHERE " + RawContacts.IS_RESTRICTED + "=0");
13414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactsColumns =
13434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                ContactsColumns.CONCRETE_CUSTOM_RINGTONE
13444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.CUSTOM_RINGTONE + ", "
13455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + contactNameColumns + ", "
13463d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + baseContactColumns + ", "
13474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_LAST_TIME_CONTACTED
13484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.LAST_TIME_CONTACTED + ", "
13494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL
13504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.SEND_TO_VOICEMAIL + ", "
13514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_STARRED
13524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                        + " AS " + Contacts.STARRED + ", "
13534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_TIMES_CONTACTED
13543d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        + " AS " + Contacts.TIMES_CONTACTED;
13554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        String contactsSelect = "SELECT "
13574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + ContactsColumns.CONCRETE_ID + " AS " + Contacts._ID + ","
13583d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + contactsColumns + ", "
13593d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(ContactsColumns.CONCRETE_ID, Contacts.PHOTO_URI) + ", "
13603d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(ContactsColumns.CONCRETE_ID, Contacts.PHOTO_THUMBNAIL_URI)
13614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov                + " FROM " + Tables.CONTACTS
1362fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1363fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")";
13644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
13654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.CONTACTS_ALL + " AS " + contactsSelect);
1366fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.CONTACTS_RESTRICTED + " AS " + contactsSelect
1367fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                + " WHERE " + ContactsColumns.SINGLE_IS_RESTRICTED + "=0");
1368a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1369a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        String rawEntitiesSelect = "SELECT "
1370a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContacts.CONTACT_ID + ", "
1371a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DELETED + " AS " + RawContacts.DELETED + ","
1372a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + dataColumns + ", "
1373a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + syncColumns + ", "
1374a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC1 + ", "
1375a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC2 + ", "
1376a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC3 + ", "
1377a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC4 + ", "
1378a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + RawContacts._ID + ", "
1379a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + RawContacts.Entity.DATA_ID + ","
1380a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_STARRED + " AS " + RawContacts.STARRED + ","
1381a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED + " AS "
1382a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                        + RawContacts.IS_RESTRICTED + ","
1383a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
1384a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS
1385a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.DATA + " ON ("
1386a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1387a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1388a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
1389a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.MIMETYPES + " ON ("
1390a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1391a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
1392a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1393a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1394a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
1395a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1396a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_ENTITIES + " AS "
1397a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + rawEntitiesSelect);
1398a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.RAW_ENTITIES_RESTRICTED + " AS "
1399a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + rawEntitiesSelect + " WHERE " + RawContacts.IS_RESTRICTED + "=0");
1400a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1401a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        String entitiesSelect = "SELECT "
1402a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + Contacts._ID + ", "
1403a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + RawContacts.CONTACT_ID + ", "
1404a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_DELETED + " AS " + RawContacts.DELETED + ","
1405a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_IS_RESTRICTED
1406a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                        + " AS " + RawContacts.IS_RESTRICTED + ","
1407a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + dataColumns + ", "
1408a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + syncColumns + ", "
1409a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + contactsColumns + ", "
14103d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
14113d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_URI) + ", "
14123d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                + buildPhotoUriAlias(RawContactsColumns.CONCRETE_CONTACT_ID,
14133d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov                        Contacts.PHOTO_THUMBNAIL_URI) + ", "
1414a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC1 + ", "
1415a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC2 + ", "
1416a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC3 + ", "
1417a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Data.SYNC4 + ", "
1418a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + RawContactsColumns.CONCRETE_ID + " AS " + Contacts.Entity.RAW_CONTACT_ID + ", "
1419a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + DataColumns.CONCRETE_ID + " AS " + Contacts.Entity.DATA_ID + ","
1420a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
1421a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS
1422a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " JOIN " + Tables.CONTACTS + " ON ("
1423a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   RawContactsColumns.CONCRETE_CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID + ")"
1424a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " JOIN " + Tables.RAW_CONTACTS + " AS name_raw_contact ON("
1425a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   Contacts.NAME_RAW_CONTACT_ID + "=name_raw_contact." + RawContacts._ID + ")"
1426a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.DATA + " ON ("
1427a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
1428a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
1429a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
1430a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.MIMETYPES + " ON ("
1431a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
1432a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
1433a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
1434a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                +   "' AND " + GroupsColumns.CONCRETE_ID + "="
1435a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID + ")";
1436a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1437a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.ENTITIES + " AS "
1438a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + entitiesSelect);
1439a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.ENTITIES_RESTRICTED + " AS "
1440a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                + entitiesSelect + " WHERE " + RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0");
1441a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    }
14424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
14433d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    private static String buildPhotoUriAlias(String contactIdColumn, String alias) {
14442b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        return "(CASE WHEN " + Contacts.PHOTO_ID + " IS NULL"
14452b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " OR " + Contacts.PHOTO_ID + "=0"
14462b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " THEN NULL"
14472b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " ELSE " + "'" + Contacts.CONTENT_URI + "/'||"
14482b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                        + contactIdColumn + "|| '/" + Photo.CONTENT_DIRECTORY + "'"
14492b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " END)"
14502b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov                + " AS " + alias;
14513d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
14523d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
1453a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov    private static void createGroupsView(SQLiteDatabase db) {
1454a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        db.execSQL("DROP VIEW IF EXISTS " + Views.GROUPS_ALL + ";");
145589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        String groupsColumns =
145689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                Groups.ACCOUNT_NAME + ","
145789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.ACCOUNT_TYPE + ","
145889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SOURCE_ID + ","
145989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.VERSION + ","
146089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.DIRTY + ","
146189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.TITLE + ","
146289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.TITLE_RES + ","
146389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.NOTES + ","
146489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYSTEM_ID + ","
146589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.DELETED + ","
146689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.GROUP_VISIBLE + ","
146789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SHOULD_SYNC + ","
1468dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + Groups.AUTO_ADD + ","
1469dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + Groups.FAVORITES + ","
1470c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                + Groups.GROUP_IS_READ_ONLY + ","
147189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC1 + ","
147289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC2 + ","
147389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC3 + ","
147489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + Groups.SYNC4 + ","
147589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + PackagesColumns.PACKAGE + " AS " + Groups.RES_PACKAGE;
147689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
147789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        String groupsSelect = "SELECT "
147889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + GroupsColumns.CONCRETE_ID + " AS " + Groups._ID + ","
147989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + groupsColumns
148089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov                + " FROM " + Tables.GROUPS_JOIN_PACKAGES;
148189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
148289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        db.execSQL("CREATE VIEW " + Views.GROUPS_ALL + " AS " + groupsSelect);
1483b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
1484b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1485b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
1486b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
148746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion < 99) {
148846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion
148946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana                    + ", data will be lost!");
149046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
149146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.CONTACTS + ";");
149246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.RAW_CONTACTS + ";");
149346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.PACKAGES + ";");
149446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.MIMETYPES + ";");
149546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.DATA + ";");
149646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.PHONE_LOOKUP + ";");
149746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.NAME_LOOKUP + ";");
149846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.NICKNAME_LOOKUP + ";");
149946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.GROUPS + ";");
150046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.ACTIVITIES + ";");
150146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.CALLS + ";");
150246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.SETTINGS + ";");
150346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.STATUS_UPDATES + ";");
150446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
150546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // TODO: we should not be dropping agg_exceptions and contact_options. In case that
150646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // table's schema changes, we should try to preserve the data, because it was entered
150746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            // by the user and has never been synched to the server.
150846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            db.execSQL("DROP TABLE IF EXISTS " + Tables.AGGREGATION_EXCEPTIONS + ";");
150946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
151046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            onCreate(db);
151146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            return;
151246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
1513f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
151446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion);
1515a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
151608e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        boolean upgradeViewsAndTriggers = false;
151704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        boolean upgradeNameLookup = false;
151808e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov
151946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion == 99) {
152008e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
152146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            oldVersion++;
152246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
152346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana
1524a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        if (oldVersion == 100) {
1525a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            db.execSQL("CREATE INDEX IF NOT EXISTS mimetypes_mimetype_index ON "
1526a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                    + Tables.MIMETYPES + " ("
1527a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                            + MimetypesColumns.MIMETYPE + ","
1528a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                            + MimetypesColumns._ID + ");");
1529a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            updateIndexStats(db, Tables.MIMETYPES,
1530a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov                    "mimetypes_mimetype_index", "50 1 1");
1531a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
153208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1533a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov            oldVersion++;
1534a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov        }
1535a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov
1536fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        if (oldVersion == 101) {
153708e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1538fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov            oldVersion++;
1539fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov        }
1540fda634f3eeff6aed8e8dddca92fc07aa44befeddDmitri Plotnikov
154147ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov        if (oldVersion == 102) {
154208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
154347ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov            oldVersion++;
154447ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov        }
154547ab23770b9f010a5e5277cda68267fe0613a1ccDmitri Plotnikov
154636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        if (oldVersion == 103) {
154708e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1548bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey            oldVersion++;
1549bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey        }
1550bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey
155171037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov        if (oldVersion == 104 || oldVersion == 201) {
155271037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov            LegacyApiSupport.createSettingsTable(db);
155308e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
15543410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov            oldVersion++;
15553410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov        }
15563410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov
155771037c010a0b7c882284fc1ed8584a378d926b83Dmitri Plotnikov        if (oldVersion == 105) {
15585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion202(db);
155904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            upgradeNameLookup = true;
15603410a80f4aafe5685da61c217808d2bf21d55dfcDmitri Plotnikov            oldVersion = 202;
156136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        }
156236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
1563fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        if (oldVersion == 202) {
15645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion203(db);
156508e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
1566fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov            oldVersion++;
1567fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        }
1568fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
15699b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori        if (oldVersion == 203) {
157008e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
15719b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori            oldVersion++;
15729b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori        }
15739b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori
15745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (oldVersion == 204) {
15755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            upgradeToVersion205(db);
157608e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            upgradeViewsAndTriggers = true;
15775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            oldVersion++;
15785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
15795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
1580f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        if (oldVersion == 205) {
1581f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            upgrateToVersion206(db);
1582f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1583f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov            oldVersion++;
1584f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        }
1585f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov
158631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        if (oldVersion == 206) {
1587b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeToVersion300(db);
158834469970fb04b9b188b5430f592b0c956a6ea2aaDmitri Plotnikov            oldVersion = 300;
158931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
159031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
15916c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        if (oldVersion == 300) {
15926c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook            upgradeViewsAndTriggers = true;
15936c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook            oldVersion = 301;
15946c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook        }
15956c0d1eb7a960d7f8c4a42a9e0ae10487654f5f7ePaul Westbrook
1596916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        if (oldVersion == 301) {
1597916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1598916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            oldVersion = 302;
1599916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov        }
1600916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov
1601b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (oldVersion == 302) {
1602b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeEmailToVersion303(db);
1603b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            upgradeNicknameToVersion303(db);
1604b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            oldVersion = 303;
1605b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
1606b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
160708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        if (oldVersion == 303) {
160808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            upgradeToVersion304(db);
160908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            oldVersion = 304;
161008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        }
161108768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
1612f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        if (oldVersion == 304) {
1613f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee            upgradeNameLookup = true;
1614f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee            oldVersion = 305;
1615f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee        }
1616f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee
161760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        if (oldVersion == 305) {
161860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            upgradeToVersion306(db);
161960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            oldVersion = 306;
162060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        }
162160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
1622b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        if (oldVersion == 306) {
1623b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            upgradeToVersion307(db);
1624b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            oldVersion = 307;
1625b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        }
1626b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
1627743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        if (oldVersion == 307) {
1628743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov            upgradeToVersion308(db);
1629743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov            oldVersion = 308;
1630743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov        }
1631743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
163294c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        // Gingerbread upgrades
163394c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        if (oldVersion < 350) {
1634afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann            upgradeViewsAndTriggers = true;
163594c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            oldVersion = 351;
1636afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann        }
1637afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann
163894c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov        if (oldVersion == 351) {
163994c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            upgradeNameLookup = true;
164094c6c5a4a2666efc9236237b5650c73d576e8a61Dmitri Plotnikov            oldVersion = 352;
164180d7871ca31d604cbfd857661d5300bb090076dbDaniel Lehmann        }
164280d7871ca31d604cbfd857661d5300bb090076dbDaniel Lehmann
16437da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        if (oldVersion == 352) {
16447da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            upgradeToVersion353(db);
16457da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            oldVersion = 353;
16467da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        }
16477da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
1648f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        // Honeycomb upgrades
1649f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        if (oldVersion < 400) {
1650dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana            upgradeViewsAndTriggers = true;
1651f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov            upgradeToVersion400(db);
1652f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov            oldVersion = 400;
1653dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        }
1654dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana
1655f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov        if (oldVersion == 400) {
16564394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            upgradeViewsAndTriggers = true;
16574394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            upgradeToVersion401(db);
16584394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov            oldVersion = 401;
16594394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        }
16604394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
1661d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        if (oldVersion == 401) {
1662d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov            upgradeToVersion402(db);
1663d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov            oldVersion = 402;
1664d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        }
1665d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
166697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        if (oldVersion == 402) {
166797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            upgradeViewsAndTriggers = true;
166897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            upgradeToVersion403(db);
166997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov            oldVersion = 403;
167097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        }
167197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
1672a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        if (oldVersion == 403) {
1673a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1674a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov            oldVersion = 404;
1675a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        }
1676a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
1677892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (oldVersion == 404) {
1678892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1679892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            upgradeToVersion405(db);
1680892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            oldVersion = 405;
1681892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
1682892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
16832530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        if (oldVersion == 405) {
16842530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            upgradeViewsAndTriggers = true;
16852530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            upgradeToVersion406(db);
16862530512f639c4979fd7371c7dd25dd67e8118124Bai Tao            oldVersion = 406;
16872530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        }
16882530512f639c4979fd7371c7dd25dd67e8118124Bai Tao
1689cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov        if (oldVersion == 406) {
1690cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1691cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov            oldVersion = 407;
1692cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov        }
1693cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov
1694385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        if (oldVersion == 407) {
1695d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            // Obsolete
1696385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            oldVersion = 408;
1697385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        }
1698385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
16993d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        if (oldVersion == 408) {
17003d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            upgradeViewsAndTriggers = true;
17013d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            upgradeToVersion409(db);
17023d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov            oldVersion = 409;
17033d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        }
17043d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
17052b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        if (oldVersion == 409) {
17062b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov            upgradeViewsAndTriggers = true;
17072b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov            oldVersion = 410;
17082b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov        }
17092b07b826e208e464bbd85d4679aab956bef0bafcDmitri Plotnikov
1710d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        if (oldVersion == 410) {
1711d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            upgradeToVersion411(db);
1712d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov            oldVersion = 411;
1713d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        }
1714d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov
17157da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        if (oldVersion == 411) {
17167da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            // Same upgrade as 353, only on Honeycomb devices
17177da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            upgradeToVersion353(db);
17187da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov            oldVersion = 412;
17197da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        }
17207da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
1721e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov        if (oldVersion == 412) {
1722e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov            upgradeToVersion413(db);
1723e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov            oldVersion = 413;
1724e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov        }
1725e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov
172656f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee        if (oldVersion == 413) {
172756f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee            upgradeNameLookup = true;
172856f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee            oldVersion = 414;
172956f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee        }
173056f2638b49e6bca97f6aa7b0768a8f1fe6e7b72eSang-il, Lee
1731c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        if (oldVersion == 414) {
1732c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            upgradeToVersion415(db);
1733c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            upgradeViewsAndTriggers = true;
1734c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov            oldVersion = 415;
1735c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        }
1736c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov
173708e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        if (upgradeViewsAndTriggers) {
173808e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createContactsViews(db);
173908e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createGroupsView(db);
174008e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            createContactsTriggers(db);
1741916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            createContactsIndexes(db);
174208e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov            LegacyApiSupport.createViews(db);
1743916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            updateSqliteStats(db);
1744916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov            mReopenDatabase = true;
174508e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov        }
174608e50780099971e8927b258ef2ae93d44f98668cDmitri Plotnikov
174704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (upgradeNameLookup) {
174804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            rebuildNameLookup(db);
174904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
175004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
175146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        if (oldVersion != newVersion) {
175246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana            throw new IllegalStateException(
175346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana                    "error upgrading the database to version " + newVersion);
175446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana        }
1755b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
1756b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
17575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion202(SQLiteDatabase db) {
175836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL(
175936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "ALTER TABLE " + Tables.PHONE_LOOKUP +
176036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " ADD " + PhoneLookupColumns.MIN_MATCH + " TEXT;");
176136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
176236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
176336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
176436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
176536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
176636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        ");");
176736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
176836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        updateIndexStats(db, Tables.PHONE_LOOKUP,
176936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "phone_lookup_min_match_index", "10000 2 2 1");
177036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
177136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        SQLiteStatement update = db.compileStatement(
177236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                "UPDATE " + Tables.PHONE_LOOKUP +
177336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " SET " + PhoneLookupColumns.MIN_MATCH + "=?" +
177436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " WHERE " + PhoneLookupColumns.DATA_ID + "=?");
177536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
177636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        // Populate the new column
177736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        Cursor c = db.query(Tables.PHONE_LOOKUP + " JOIN " + Tables.DATA +
177836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                " ON (" + PhoneLookupColumns.DATA_ID + "=" + DataColumns.CONCRETE_ID + ")",
177936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                new String[]{Data._ID, Phone.NUMBER}, null, null, null, null, null);
178036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        try {
178136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            while (c.moveToNext()) {
178236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                long dataId = c.getLong(0);
178336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                String number = c.getString(1);
178436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                if (!TextUtils.isEmpty(number)) {
178536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.bindString(1, PhoneNumberUtils.toCallerIDMinMatch(number));
178636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.bindLong(2, dataId);
178736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    update.execute();
178836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                }
178936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            }
179036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        } finally {
179136045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            c.close();
179236045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        }
179336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    }
179436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
17955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion203(SQLiteDatabase db) {
1796758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // Garbage-collect first. A bug in Eclair was sometimes leaving
1797758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // raw_contacts in the database that no longer had contacts associated
1798758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // with them.  To avoid failures during this database upgrade, drop
1799758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        // the orphaned raw_contacts.
1800758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov        db.execSQL(
1801758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                "DELETE FROM raw_contacts" +
1802758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                " WHERE contact_id NOT NULL" +
1803758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov                " AND contact_id NOT IN (SELECT _id FROM contacts)");
1804758a7562d72b0a6ed336beac508eedf7b369fa20Dmitri Plotnikov
1805fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1806fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "ALTER TABLE " + Tables.CONTACTS +
1807fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " ADD " + Contacts.NAME_RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)");
1808fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1809fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "ALTER TABLE " + Tables.RAW_CONTACTS +
18104394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " ADD contact_in_visible_group INTEGER NOT NULL DEFAULT 0");
1811fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1812fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // For each Contact, find the RawContact that contributed the display name
1813fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1814fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1815fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.NAME_RAW_CONTACT_ID + "=(" +
1816fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " SELECT " + RawContacts._ID +
1817fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.RAW_CONTACTS +
1818fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
1819fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " AND " + RawContactsColumns.CONCRETE_DISPLAY_NAME + "=" +
1820fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                                Tables.CONTACTS + "." + Contacts.DISPLAY_NAME +
1821fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " ORDER BY " + RawContacts._ID +
1822fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " LIMIT 1)"
1823fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1824fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1825fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_name_raw_contact_id_index ON " + Tables.CONTACTS + " (" +
1826fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.NAME_RAW_CONTACT_ID +
1827fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1828fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1829fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // If for some unknown reason we missed some names, let's make sure there are
1830fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // no contacts without a name, picking a raw contact "at random".
1831fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1832fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1833fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.NAME_RAW_CONTACT_ID + "=(" +
1834fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " SELECT " + RawContacts._ID +
1835fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.RAW_CONTACTS +
1836fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID +
1837fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " ORDER BY " + RawContacts._ID +
1838fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " LIMIT 1)" +
1839fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " WHERE " + Contacts.NAME_RAW_CONTACT_ID + " IS NULL"
1840fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1841fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1842fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // Wipe out DISPLAY_NAME on the Contacts table as it is no longer in use.
1843fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1844fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.CONTACTS +
1845fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                " SET " + Contacts.DISPLAY_NAME + "=NULL"
1846fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1847fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1848fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // Copy the IN_VISIBLE_GROUP flag down to all raw contacts to allow
1849fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        // indexing on (display_name, in_visible_group)
1850fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL(
1851fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                "UPDATE " + Tables.RAW_CONTACTS +
18524394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " SET contact_in_visible_group=(" +
1853fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        "SELECT " + Contacts.IN_VISIBLE_GROUP +
1854fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                        " FROM " + Tables.CONTACTS +
1855bcbd6a5cdd2d1aa6531c592428dc20e0282486c3Dmitri Plotnikov                        " WHERE " + Contacts._ID + "=" + RawContacts.CONTACT_ID + ")" +
1856bcbd6a5cdd2d1aa6531c592428dc20e0282486c3Dmitri Plotnikov                " WHERE " + RawContacts.CONTACT_ID + " NOT NULL"
1857fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        );
1858fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1859fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
18604394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
1861fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                RawContactsColumns.DISPLAY_NAME + " COLLATE LOCALIZED ASC" +
1862fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1863fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
1864fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("DROP INDEX contacts_visible_index");
1865fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        db.execSQL("CREATE INDEX contacts_visible_index ON " + Tables.CONTACTS + " (" +
1866fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                Contacts.IN_VISIBLE_GROUP +
1867fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov        ");");
1868fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov    }
1869fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
18705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeToVersion205(SQLiteDatabase db) {
18715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
18725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.DISPLAY_NAME_ALTERNATIVE + " TEXT;");
18735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
18745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.PHONETIC_NAME + " TEXT;");
18755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
18765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                + " ADD " + RawContacts.PHONETIC_NAME_STYLE + " INTEGER;");
18775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
1878de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " ADD " + RawContacts.SORT_KEY_PRIMARY
1879de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " TEXT COLLATE " + ContactsProvider2.PHONEBOOK_COLLATOR_NAME + ";");
18805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
1881de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " ADD " + RawContacts.SORT_KEY_ALTERNATIVE
1882de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa                + " TEXT COLLATE " + ContactsProvider2.PHONEBOOK_COLLATOR_NAME + ";");
18835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        final Locale locale = Locale.getDefault();
18855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
188651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        NameSplitter splitter = createNameSplitter();
18875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement rawContactUpdate = db.compileStatement(
18895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.RAW_CONTACTS +
18905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
18915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.DISPLAY_NAME_PRIMARY + "=?," +
18925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," +
18935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.PHONETIC_NAME + "=?," +
18945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.PHONETIC_NAME_STYLE + "=?," +
18955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.SORT_KEY_PRIMARY + "=?," +
18965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        RawContacts.SORT_KEY_ALTERNATIVE + "=?" +
18975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + RawContacts._ID + "=?");
18985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
18995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        upgradeStructuredNamesToVersion205(db, rawContactUpdate, splitter);
19005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        upgradeOrganizationsToVersion205(db, rawContactUpdate, splitter);
19015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("DROP INDEX raw_contact_sort_key1_index");
19035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key1_index ON " + Tables.RAW_CONTACTS + " (" +
19044394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
19055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.SORT_KEY_PRIMARY +
19065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        ");");
19075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        db.execSQL("CREATE INDEX raw_contact_sort_key2_index ON " + Tables.RAW_CONTACTS + " (" +
19094394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "contact_in_visible_group" + "," +
19105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.SORT_KEY_ALTERNATIVE +
19115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        ");");
19125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
19135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private interface StructName205Query {
19155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String TABLE = Tables.DATA_JOIN_RAW_CONTACTS;
19165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String COLUMNS[] = {
19185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.CONCRETE_ID,
19195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Data.RAW_CONTACT_ID,
19205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_SOURCE,
19215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                RawContacts.DISPLAY_NAME_PRIMARY,
19225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PREFIX,
19235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.GIVEN_NAME,
19245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.MIDDLE_NAME,
19255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.FAMILY_NAME,
19265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.SUFFIX,
19275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_FAMILY_NAME,
19285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_MIDDLE_NAME,
19295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructuredName.PHONETIC_GIVEN_NAME,
19305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        };
19315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int ID = 0;
19335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int RAW_CONTACT_ID = 1;
19345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int DISPLAY_NAME_SOURCE = 2;
19355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int DISPLAY_NAME = 3;
19365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PREFIX = 4;
19375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int GIVEN_NAME = 5;
19385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int MIDDLE_NAME = 6;
19395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int FAMILY_NAME = 7;
19405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int SUFFIX = 8;
19415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_FAMILY_NAME = 9;
19425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_MIDDLE_NAME = 10;
19435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_GIVEN_NAME = 11;
19445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
19455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeStructuredNamesToVersion205(SQLiteDatabase db,
19475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement rawContactUpdate, NameSplitter splitter) {
19485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        // Process structured names to detect the style of the full name and phonetic name
19505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        long mMimeType;
19525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
19535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            mMimeType = DatabaseUtils.longForQuery(db,
19545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    "SELECT " + MimetypesColumns._ID +
19555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    " FROM " + Tables.MIMETYPES +
19565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    " WHERE " + MimetypesColumns.MIMETYPE
19575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                            + "='" + StructuredName.CONTENT_ITEM_TYPE + "'", null);
19585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } catch (SQLiteDoneException e) {
19595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            // No structured names in the database
19605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            return;
19615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
19625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement structuredNameUpdate = db.compileStatement(
19645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.DATA +
19655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
19665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.FULL_NAME_STYLE + "=?," +
19675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.DISPLAY_NAME + "=?," +
19685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        StructuredName.PHONETIC_NAME_STYLE + "=?" +
19695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + Data._ID + "=?");
19705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        NameSplitter.Name name = new NameSplitter.Name();
19725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        StringBuilder sb = new StringBuilder();
19735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        Cursor cursor = db.query(StructName205Query.TABLE,
19745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                StructName205Query.COLUMNS,
19755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=" + mMimeType, null, null, null, null);
19765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
19775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            while (cursor.moveToNext()) {
19785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long dataId = cursor.getLong(StructName205Query.ID);
19795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long rawContactId = cursor.getLong(StructName205Query.RAW_CONTACT_ID);
19805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                int displayNameSource = cursor.getInt(StructName205Query.DISPLAY_NAME_SOURCE);
19815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String displayName = cursor.getString(StructName205Query.DISPLAY_NAME);
19825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.clear();
19845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.prefix = cursor.getString(StructName205Query.PREFIX);
19855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.givenNames = cursor.getString(StructName205Query.GIVEN_NAME);
19865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.middleName = cursor.getString(StructName205Query.MIDDLE_NAME);
19875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.familyName = cursor.getString(StructName205Query.FAMILY_NAME);
19885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.suffix = cursor.getString(StructName205Query.SUFFIX);
19895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticFamilyName = cursor.getString(StructName205Query.PHONETIC_FAMILY_NAME);
19905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticMiddleName = cursor.getString(StructName205Query.PHONETIC_MIDDLE_NAME);
19915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                name.phoneticGivenName = cursor.getString(StructName205Query.PHONETIC_GIVEN_NAME);
19925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
19935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                upgradeNameToVersion205(dataId, rawContactId, displayNameSource, displayName, name,
19945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        structuredNameUpdate, rawContactUpdate, splitter, sb);
19955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
19965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } finally {
19975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            cursor.close();
19985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
19995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
20005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeNameToVersion205(long dataId, long rawContactId, int displayNameSource,
20025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String currentDisplayName, NameSplitter.Name name,
20035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement structuredNameUpdate, SQLiteStatement rawContactUpdate,
20045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            NameSplitter splitter, StringBuilder sb) {
20055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        splitter.guessNameStyle(name);
2007ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        int unadjustedFullNameStyle = name.fullNameStyle;
20085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        name.fullNameStyle = splitter.getAdjustedFullNameStyle(name.fullNameStyle);
20095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String displayName = splitter.join(name, true);
20105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
2011ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        // Don't update database with the adjusted fullNameStyle as it is locale
2012ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        // related
2013ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao        structuredNameUpdate.bindLong(1, unadjustedFullNameStyle);
20145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        DatabaseUtils.bindObjectToProgram(structuredNameUpdate, 2, displayName);
20155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.bindLong(3, name.phoneticNameStyle);
20165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.bindLong(4, dataId);
20175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        structuredNameUpdate.execute();
20185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (displayNameSource == DisplayNameSources.STRUCTURED_NAME) {
20205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String displayNameAlternative = splitter.join(name, false);
20215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String phoneticName = splitter.joinPhoneticName(name);
20225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String sortKey = null;
20235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String sortKeyAlternative = null;
20245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            if (phoneticName != null) {
20265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKey = sortKeyAlternative = phoneticName;
2027ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao            } else if (name.fullNameStyle == FullNameStyle.CHINESE ||
2028ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                    name.fullNameStyle == FullNameStyle.CJK) {
2029ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                sortKey = sortKeyAlternative = ContactLocaleUtils.getIntance()
2030ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                        .getSortKey(displayName, name.fullNameStyle);
20315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
20325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            if (sortKey == null) {
20345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKey = displayName;
20355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                sortKeyAlternative = displayNameAlternative;
20365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
20375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            updateRawContact205(rawContactUpdate, rawContactId, displayName,
20395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    displayNameAlternative, name.phoneticNameStyle, phoneticName, sortKey,
20405dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    sortKeyAlternative);
20415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
20425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
20435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private interface Organization205Query {
20455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String TABLE = Tables.DATA_JOIN_RAW_CONTACTS;
20465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        String COLUMNS[] = {
20485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                DataColumns.CONCRETE_ID,
20495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Data.RAW_CONTACT_ID,
20505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Organization.COMPANY,
20515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                Organization.PHONETIC_NAME,
20525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        };
20535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int ID = 0;
20555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int RAW_CONTACT_ID = 1;
20565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int COMPANY = 2;
20575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        int PHONETIC_NAME = 3;
20585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
20595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void upgradeOrganizationsToVersion205(SQLiteDatabase db,
20615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            SQLiteStatement rawContactUpdate, NameSplitter splitter) {
2062b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeType = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
20635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        SQLiteStatement organizationUpdate = db.compileStatement(
20655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                "UPDATE " + Tables.DATA +
20665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " SET " +
20675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        Organization.PHONETIC_NAME_STYLE + "=?" +
20685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                " WHERE " + Data._ID + "=?");
20695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        Cursor cursor = db.query(Organization205Query.TABLE, Organization205Query.COLUMNS,
2071b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=" + mimeType + " AND "
20725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        + RawContacts.DISPLAY_NAME_SOURCE + "=" + DisplayNameSources.ORGANIZATION,
20735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                null, null, null, null);
20745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        try {
20755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            while (cursor.moveToNext()) {
20765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long dataId = cursor.getLong(Organization205Query.ID);
20775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                long rawContactId = cursor.getLong(Organization205Query.RAW_CONTACT_ID);
20785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String company = cursor.getString(Organization205Query.COMPANY);
20795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String phoneticName = cursor.getString(Organization205Query.PHONETIC_NAME);
20805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                int phoneticNameStyle = splitter.guessPhoneticNameStyle(phoneticName);
20825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.bindLong(1, phoneticNameStyle);
20845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.bindLong(2, dataId);
20855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                organizationUpdate.execute();
20865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                String sortKey = null;
20885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                if (phoneticName == null && company != null) {
20895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    int nameStyle = splitter.guessFullNameStyle(company);
20905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    nameStyle = splitter.getAdjustedFullNameStyle(nameStyle);
2091ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                    if (nameStyle == FullNameStyle.CHINESE ||
2092ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                            nameStyle == FullNameStyle.CJK ) {
2093ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                        sortKey = ContactLocaleUtils.getIntance()
2094ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao                                .getSortKey(company, nameStyle);
20955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    }
20965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                }
20975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
20985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                if (sortKey == null) {
20995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                    sortKey = company;
21005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                }
21015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
21025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                updateRawContact205(rawContactUpdate, rawContactId, company,
21035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov                        company, phoneticNameStyle, phoneticName, sortKey, sortKey);
21045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            }
21055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } finally {
21065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            cursor.close();
21075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
21085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
21095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
21105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void updateRawContact205(SQLiteStatement rawContactUpdate, long rawContactId,
21115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String displayName, String displayNameAlternative, int phoneticNameStyle,
21125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String phoneticName, String sortKeyPrimary, String sortKeyAlternative) {
21135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 1, displayName);
21145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 2, displayNameAlternative);
21155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 3, phoneticName);
21165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.bindLong(4, phoneticNameStyle);
21175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 5, sortKeyPrimary);
21185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        bindString(rawContactUpdate, 6, sortKeyAlternative);
21195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.bindLong(7, rawContactId);
21205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        rawContactUpdate.execute();
21215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
21225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
2123f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov    private void upgrateToVersion206(SQLiteDatabase db) {
2124f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov        db.execSQL("ALTER TABLE " + Tables.RAW_CONTACTS
2125f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov                + " ADD " + RawContacts.NAME_VERIFIED + " INTEGER NOT NULL DEFAULT 0;");
2126f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov    }
2127f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov
212831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    private interface Organization300Query {
212931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String TABLE = Tables.DATA;
213031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
213131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String SELECTION = DataColumns.MIMETYPE_ID + "=?";
213231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
213331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        String COLUMNS[] = {
213431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization._ID,
213531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.RAW_CONTACT_ID,
213631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.COMPANY,
213731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                Organization.TITLE
213831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        };
213931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
214031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int ID = 0;
214131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int RAW_CONTACT_ID = 1;
214231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int COMPANY = 2;
214331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        int TITLE = 3;
214431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    }
214531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
214631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    /**
214731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     * Fix for the bug where name lookup records for organizations would get removed by
214831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     * unrelated updates of the data rows.
214931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov     */
2150b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeToVersion300(SQLiteDatabase db) {
2151b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeType = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
2152b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeType == -1) {
215331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            return;
215431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
215531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
215631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        ContentValues values = new ContentValues();
215731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
215831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        // Find all data rows with the mime type "organization"
215931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        Cursor cursor = db.query(Organization300Query.TABLE, Organization300Query.COLUMNS,
2160b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Organization300Query.SELECTION, new String[] {String.valueOf(mimeType)},
216131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                null, null, null);
216231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        try {
216331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            while (cursor.moveToNext()) {
216431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                long dataId = cursor.getLong(Organization300Query.ID);
216531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                long rawContactId = cursor.getLong(Organization300Query.RAW_CONTACT_ID);
216631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                String company = cursor.getString(Organization300Query.COMPANY);
216731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                String title = cursor.getString(Organization300Query.TITLE);
216831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
216931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                // First delete name lookup if there is any (chances are there won't be)
217031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                db.delete(Tables.NAME_LOOKUP, NameLookupColumns.DATA_ID + "=?",
217131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                        new String[]{String.valueOf(dataId)});
217231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
217331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                // Now insert two name lookup records: one for company name, one for title
217431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.DATA_ID, dataId);
217531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
217631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                values.put(NameLookupColumns.NAME_TYPE, NameLookupType.ORGANIZATION);
217731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
217831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                if (!TextUtils.isEmpty(company)) {
217931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME,
218031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                            NameNormalizer.normalize(company));
218131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
218231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                }
218331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
218431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                if (!TextUtils.isEmpty(title)) {
218531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME,
218631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                            NameNormalizer.normalize(title));
218731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
218831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov                }
218931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            }
219031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        } finally {
219131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov            cursor.close();
219231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov        }
219331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov    }
219431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov
2195b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private static final class Upgrade303Query {
2196b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
2197b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2198b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String SELECTION =
2199b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=?" +
2200b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    " AND " + Data._ID + " NOT IN " +
2201b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    "(SELECT " + NameLookupColumns.DATA_ID + " FROM " + Tables.NAME_LOOKUP + ")" +
2202b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                    " AND " + Data.DATA1 + " NOT NULL";
2203b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2204b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final String COLUMNS[] = {
2205b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data._ID,
2206b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data.RAW_CONTACT_ID,
2207b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Data.DATA1,
2208b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        };
2209b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2210b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int ID = 0;
2211b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
2212b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        public static final int DATA1 = 2;
2213b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2214b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2215b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    /**
2216b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * The {@link ContactsProvider2#update} method was deleting name lookup for new
2217b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * emails during the sync.  We need to restore the lost name lookup rows.
2218b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     */
2219b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeEmailToVersion303(SQLiteDatabase db) {
2220b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Email.CONTENT_ITEM_TYPE);
2221b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeTypeId == -1) {
2222b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return;
2223b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2224b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2225b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        ContentValues values = new ContentValues();
2226b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2227b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        // Find all data rows with the mime type "email" that are missing name lookup
2228b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Cursor cursor = db.query(Upgrade303Query.TABLE, Upgrade303Query.COLUMNS,
2229b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Upgrade303Query.SELECTION, new String[] {String.valueOf(mimeTypeId)},
2230b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                null, null, null);
2231b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2232b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            while (cursor.moveToNext()) {
2233b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long dataId = cursor.getLong(Upgrade303Query.ID);
2234b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long rawContactId = cursor.getLong(Upgrade303Query.RAW_CONTACT_ID);
2235b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                String value = cursor.getString(Upgrade303Query.DATA1);
2236b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                value = extractHandleFromEmailAddress(value);
2237b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2238b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                if (value != null) {
2239b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.DATA_ID, dataId);
2240b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
2241b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.NAME_TYPE, NameLookupType.EMAIL_BASED_NICKNAME);
2242b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    values.put(NameLookupColumns.NORMALIZED_NAME, NameNormalizer.normalize(value));
2243b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    db.insert(Tables.NAME_LOOKUP, null, values);
2244b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                }
2245b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            }
2246b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } finally {
2247b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            cursor.close();
2248b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2249b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2250b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2251b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    /**
2252b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * The {@link ContactsProvider2#update} method was deleting name lookup for new
2253b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     * nicknames during the sync.  We need to restore the lost name lookup rows.
2254b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov     */
2255b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private void upgradeNicknameToVersion303(SQLiteDatabase db) {
2256b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Nickname.CONTENT_ITEM_TYPE);
2257b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (mimeTypeId == -1) {
2258b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return;
2259b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2260b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2261b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        ContentValues values = new ContentValues();
2262b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2263b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        // Find all data rows with the mime type "nickname" that are missing name lookup
2264b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Cursor cursor = db.query(Upgrade303Query.TABLE, Upgrade303Query.COLUMNS,
2265b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                Upgrade303Query.SELECTION, new String[] {String.valueOf(mimeTypeId)},
2266b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                null, null, null);
2267b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2268b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            while (cursor.moveToNext()) {
2269b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long dataId = cursor.getLong(Upgrade303Query.ID);
2270b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                long rawContactId = cursor.getLong(Upgrade303Query.RAW_CONTACT_ID);
2271b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                String value = cursor.getString(Upgrade303Query.DATA1);
2272b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2273b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.DATA_ID, dataId);
2274b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.RAW_CONTACT_ID, rawContactId);
2275b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.NAME_TYPE, NameLookupType.NICKNAME);
2276b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                values.put(NameLookupColumns.NORMALIZED_NAME, NameNormalizer.normalize(value));
2277b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                db.insert(Tables.NAME_LOOKUP, null, values);
2278b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            }
2279b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } finally {
2280b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            cursor.close();
2281b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2282b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2283b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
228451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void upgradeToVersion304(SQLiteDatabase db) {
228551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        // Mimetype table requires an index on mime type
228651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS mime_type ON " + Tables.MIMETYPES + " (" +
228751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                MimetypesColumns.MIMETYPE +
228851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        ");");
228951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
229051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
229160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann    private void upgradeToVersion306(SQLiteDatabase db) {
229260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        // Fix invalid lookup that was used for Exchange contacts (it was not escaped)
229360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        // It happened when a new contact was created AND synchronized
229460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final StringBuilder lookupKeyBuilder = new StringBuilder();
229560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final SQLiteStatement updateStatement = db.compileStatement(
229660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "UPDATE contacts " +
229760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "SET lookup=? " +
229860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "WHERE _id=?");
229960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        final Cursor contactIdCursor = db.rawQuery(
230060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "SELECT DISTINCT contact_id " +
230160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "FROM raw_contacts " +
230260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                "WHERE deleted=0 AND account_type='com.android.exchange'",
230360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                null);
230460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        try {
230560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            while (contactIdCursor.moveToNext()) {
230660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                final long contactId = contactIdCursor.getLong(0);
230760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                lookupKeyBuilder.setLength(0);
230860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                final Cursor c = db.rawQuery(
230960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "SELECT account_type, account_name, _id, sourceid, display_name " +
231060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "FROM raw_contacts " +
231160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "WHERE contact_id=? " +
231260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        "ORDER BY _id",
231360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        new String[] { String.valueOf(contactId) });
231460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                try {
231560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    while (c.moveToNext()) {
231660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                        ContactLookupKey.appendToLookupKey(lookupKeyBuilder,
231760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(0),
231860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(1),
231960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getLong(2),
232060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(3),
232160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                                c.getString(4));
232260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    }
232360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                } finally {
232460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    c.close();
232560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                }
232660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
232760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                if (lookupKeyBuilder.length() == 0) {
232860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    updateStatement.bindNull(1);
232960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                } else {
233060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                    updateStatement.bindString(1, Uri.encode(lookupKeyBuilder.toString()));
233160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                }
233260de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                updateStatement.bindLong(2, contactId);
233360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
233460de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann                updateStatement.execute();
233560de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            }
233660de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        } finally {
233760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            updateStatement.close();
233860de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann            contactIdCursor.close();
233960de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann        }
234060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann    }
234160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann
2342b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    private void upgradeToVersion307(SQLiteDatabase db) {
2343b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        db.execSQL("CREATE TABLE properties (" +
2344b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                "property_key TEXT PRIMARY_KEY, " +
2345b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                "property_value TEXT" +
2346b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ");");
2347b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
2348b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
2349743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov    private void upgradeToVersion308(SQLiteDatabase db) {
23504394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE accounts (" +
23514394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "account_name TEXT, " +
23524394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "account_type TEXT " +
23534394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
2354743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
23554394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO accounts " +
23564394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                "SELECT DISTINCT account_name, account_type FROM raw_contacts");
2357743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov    }
2358743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov
2359f3082210d83492b4a8591c82e56291514547f5a5Dmitri Plotnikov    private void upgradeToVersion400(SQLiteDatabase db) {
2360dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        db.execSQL("ALTER TABLE " + Tables.GROUPS
2361dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + " ADD " + Groups.FAVORITES + " INTEGER NOT NULL DEFAULT 0;");
2362dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana        db.execSQL("ALTER TABLE " + Tables.GROUPS
2363dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana                + " ADD " + Groups.AUTO_ADD + " INTEGER NOT NULL DEFAULT 0;");
2364dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana    }
2365dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana
23667da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov    private void upgradeToVersion353(SQLiteDatabase db) {
23677da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov        db.execSQL("DELETE FROM contacts " +
23687da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov                "WHERE NOT EXISTS (SELECT 1 FROM raw_contacts WHERE contact_id=contacts._id)");
23697da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov    }
23707da074dc59f256a63201439cc9ae24bd2e347a06Dmitri Plotnikov
237151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void rebuildNameLookup(SQLiteDatabase db) {
237251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
237351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        insertNameLookup(db);
237451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        createContactsIndexes(db);
237551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
237651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
237704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
237851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     * Regenerates all locale-sensitive data: nickname_lookup, name_lookup and sort keys.
237904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
238051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    public void setLocale(ContactsProvider2 provider, Locale locale) {
238151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        Log.i(TAG, "Switching to locale " + locale);
238204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
2383c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamilton        long start = SystemClock.uptimeMillis();
238451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
238551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.setLocale(locale);
238651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.beginTransaction();
238751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
238851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX raw_contact_sort_key1_index");
238951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX raw_contact_sort_key2_index");
239051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.execSQL("DROP INDEX IF EXISTS name_lookup_index");
239151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
239251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            loadNicknameLookupTable(db);
239351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertNameLookup(db);
239451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            rebuildSortKeys(db, provider);
239551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            createContactsIndexes(db);
239651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.setTransactionSuccessful();
239751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
239851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            db.endTransaction();
239951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
240051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
2401c085b3eeebf13ebdfb197444747354a1d6eced2bJeff Hamilton        Log.i(TAG, "Locale change completed in " + (SystemClock.uptimeMillis() - start) + "ms");
240251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
240351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
240451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    /**
240551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     * Regenerates sort keys for all contacts.
240651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov     */
240751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void rebuildSortKeys(SQLiteDatabase db, ContactsProvider2 provider) {
240851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        Cursor cursor = db.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID},
240951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                null, null, null, null, null);
241051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
241151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            while (cursor.moveToNext()) {
241251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                long rawContactId = cursor.getLong(0);
241351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                provider.updateRawContactDisplayName(db, rawContactId);
241451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            }
241551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
241651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            cursor.close();
241751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
241851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    }
241951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
242051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov    private void insertNameLookup(SQLiteDatabase db) {
242104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NAME_LOOKUP);
242204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
242304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        SQLiteStatement nameLookupInsert = db.compileStatement(
242404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                "INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "("
242504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.RAW_CONTACT_ID + ","
242604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.DATA_ID + ","
242704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.NAME_TYPE + ","
242804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        + NameLookupColumns.NORMALIZED_NAME +
242904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                ") VALUES (?,?,?,?)");
243004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
243151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
243251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertStructuredNameLookup(db, nameLookupInsert);
243351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertOrganizationLookup(db, nameLookupInsert);
243451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertEmailLookup(db, nameLookupInsert);
243551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            insertNicknameLookup(db, nameLookupInsert);
243651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
243751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            nameLookupInsert.close();
243851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        }
243904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
244004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
244104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class StructuredNameQuery {
244204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
244304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
244404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
244504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
244604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
244704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
244804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName._ID,
244904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName.RAW_CONTACT_ID,
245004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredName.DISPLAY_NAME,
245104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
245204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
245304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
245404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
245504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int DISPLAY_NAME = 2;
245604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
245704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
245804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private class StructuredNameLookupBuilder extends NameLookupBuilder {
245904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
246004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        private final SQLiteStatement mNameLookupInsert;
246104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        private final CommonNicknameCache mCommonNicknameCache;
246204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
246304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public StructuredNameLookupBuilder(NameSplitter splitter,
246404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                CommonNicknameCache commonNicknameCache, SQLiteStatement nameLookupInsert) {
246504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            super(splitter);
246604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            this.mCommonNicknameCache = commonNicknameCache;
246704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            this.mNameLookupInsert = nameLookupInsert;
246804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
246904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
247004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        @Override
247104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        protected void insertNameLookup(long rawContactId, long dataId, int lookupType,
247204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String name) {
247304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            if (!TextUtils.isEmpty(name)) {
247404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                ContactsDatabaseHelper.this.insertNormalizedNameLookup(mNameLookupInsert,
247504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        rawContactId, dataId, lookupType, name);
247604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
247704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
247804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
247904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        @Override
248004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        protected String[] getCommonNicknameClusters(String normalizedName) {
248104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return mCommonNicknameCache.getCommonNicknameClusters(normalizedName);
248204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
248304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
248404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
248504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
248604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all structured names in the database.
248704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
248804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertStructuredNameLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
2489d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov        NameSplitter nameSplitter = createNameSplitter();
2490d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov        NameLookupBuilder nameLookupBuilder = new StructuredNameLookupBuilder(nameSplitter,
249104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                new CommonNicknameCache(db), nameLookupInsert);
249204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, StructuredName.CONTENT_ITEM_TYPE);
249304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(StructuredNameQuery.TABLE, StructuredNameQuery.COLUMNS,
249404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                StructuredNameQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
249504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
249604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
249704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
249804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(StructuredNameQuery.ID);
249904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(StructuredNameQuery.RAW_CONTACT_ID);
250004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String name = cursor.getString(StructuredNameQuery.DISPLAY_NAME);
2501d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov                int fullNameStyle = nameSplitter.guessFullNameStyle(name);
250251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                fullNameStyle = nameSplitter.getAdjustedFullNameStyle(fullNameStyle);
2503d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov                nameLookupBuilder.insertNameLookup(rawContactId, dataId, name, fullNameStyle);
250404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
250504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
250604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
250704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
250804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
250904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
251004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class OrganizationQuery {
251104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
251204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
251304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
251404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
251504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
251604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
251704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization._ID,
251804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.RAW_CONTACT_ID,
251904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.COMPANY,
252004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Organization.TITLE,
252104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
252204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
252304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
252404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
252504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int COMPANY = 2;
252604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int TITLE = 3;
252704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
252804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
252904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
253004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all organizations in the database.
253104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
253204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertOrganizationLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
253304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Organization.CONTENT_ITEM_TYPE);
253404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(OrganizationQuery.TABLE, OrganizationQuery.COLUMNS,
253504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                OrganizationQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
253604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
253704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
253804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
253904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(OrganizationQuery.ID);
254004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(OrganizationQuery.RAW_CONTACT_ID);
254104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String organization = cursor.getString(OrganizationQuery.COMPANY);
254204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String title = cursor.getString(OrganizationQuery.TITLE);
254304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
254404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.ORGANIZATION, organization);
254504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
254604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.ORGANIZATION, title);
254704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
254804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
254904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
255004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
255104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
255204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
255304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class EmailQuery {
255404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
255504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
255604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
255704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
255804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
255904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
256004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email._ID,
256104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email.RAW_CONTACT_ID,
256204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Email.ADDRESS,
256304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
256404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
256504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
256604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
256704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ADDRESS = 2;
256804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
256904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
257004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
257104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all email addresses in the database.
257204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
257304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertEmailLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
257404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Email.CONTENT_ITEM_TYPE);
257504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(EmailQuery.TABLE, EmailQuery.COLUMNS,
257604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                EmailQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
257704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
257804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
257904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
258004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(EmailQuery.ID);
258104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(EmailQuery.RAW_CONTACT_ID);
258204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String address = cursor.getString(EmailQuery.ADDRESS);
258304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                address = extractHandleFromEmailAddress(address);
258404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
258504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.EMAIL_BASED_NICKNAME, address);
258604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
258704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
258804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
258904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
259004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
259104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
259204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private static final class NicknameQuery {
259304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String TABLE = Tables.DATA;
259404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
259504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String SELECTION =
259604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                DataColumns.MIMETYPE_ID + "=? AND " + Data.DATA1 + " NOT NULL";
259704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
259804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final String COLUMNS[] = {
259904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname._ID,
260004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname.RAW_CONTACT_ID,
260104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Nickname.NAME,
260204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        };
260304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
260404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int ID = 0;
260504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int RAW_CONTACT_ID = 1;
260604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        public static final int NAME = 2;
260704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
260804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
260904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
261004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts name lookup rows for all nicknames in the database.
261104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
261204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertNicknameLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) {
261304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Nickname.CONTENT_ITEM_TYPE);
261404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        Cursor cursor = db.query(NicknameQuery.TABLE, NicknameQuery.COLUMNS,
261504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                NicknameQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)},
261604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                null, null, null);
261704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        try {
261804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            while (cursor.moveToNext()) {
261904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long dataId = cursor.getLong(NicknameQuery.ID);
262004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                long rawContactId = cursor.getLong(NicknameQuery.RAW_CONTACT_ID);
262104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                String nickname = cursor.getString(NicknameQuery.NAME);
262204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                insertNameLookup(nameLookupInsert, rawContactId, dataId,
262304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                        NameLookupType.NICKNAME, nickname);
262404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            }
262504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        } finally {
262604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            cursor.close();
262704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
262804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
262904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
263004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    /**
263104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     * Inserts a record in the {@link Tables#NAME_LOOKUP} table.
263204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov     */
263304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    public void insertNameLookup(SQLiteStatement stmt, long rawContactId, long dataId,
263404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            int lookupType, String name) {
263504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (TextUtils.isEmpty(name)) {
263604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return;
263704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
263804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
263904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        String normalized = NameNormalizer.normalize(name);
264004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        if (TextUtils.isEmpty(normalized)) {
264104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            return;
264204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        }
264304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
264404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        insertNormalizedNameLookup(stmt, rawContactId, dataId, lookupType, normalized);
264504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
264604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
264704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    private void insertNormalizedNameLookup(SQLiteStatement stmt, long rawContactId, long dataId,
264804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov            int lookupType, String normalizedName) {
264904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(1, rawContactId);
265004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(2, dataId);
265104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindLong(3, lookupType);
265204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.bindString(4, normalizedName);
265304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        stmt.executeInsert();
265404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
265504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
26564394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    /**
26574394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov     * Changing the VISIBLE bit from a field on both RawContacts and Contacts to a separate table.
26584394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov     */
26594394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    private void upgradeToVersion401(SQLiteDatabase db) {
26604394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.VISIBLE_CONTACTS + " (" +
26614394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
26624394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        ");");
26634394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.VISIBLE_CONTACTS +
26644394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " SELECT " + Contacts._ID +
26654394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " FROM " + Tables.CONTACTS +
26664394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                " WHERE " + Contacts.IN_VISIBLE_GROUP + "!=0");
26674394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("DROP INDEX contacts_visible_index");
26684394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov    }
26694394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
2670d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    /**
2671d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov     * Introducing a new table: directories.
2672d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov     */
2673d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    private void upgradeToVersion402(SQLiteDatabase db) {
2674d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov        createDirectoriesTable(db);
2675d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov    }
2676d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov
267797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    private void upgradeToVersion403(SQLiteDatabase db) {
267897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
267997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        createDirectoriesTable(db);
268097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
268197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("ALTER TABLE raw_contacts"
268297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + " ADD raw_contact_is_read_only INTEGER NOT NULL DEFAULT 0;");
268397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
268497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov        db.execSQL("ALTER TABLE data"
268597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov                + " ADD is_read_only INTEGER NOT NULL DEFAULT 0;");
268697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov    }
268797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov
2688892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    private void upgradeToVersion405(SQLiteDatabase db) {
2689892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS phone_lookup;");
2690892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        // Private phone numbers table used for lookup
2691892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" +
2692892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID
2693892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " INTEGER REFERENCES data(_id) NOT NULL," +
2694892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID
2695892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
2696892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL," +
2697892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL" +
2698892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2699892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2700892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" +
2701892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.NORMALIZED_NUMBER + "," +
2702892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
2703892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
2704892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2705892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2706892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        db.execSQL("CREATE INDEX phone_lookup_min_match_index ON " + Tables.PHONE_LOOKUP + " (" +
2707892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.MIN_MATCH + "," +
2708892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + "," +
2709892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                PhoneLookupColumns.DATA_ID +
2710892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ");");
2711892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2712892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        final long mimeTypeId = lookupMimeTypeId(db, Phone.CONTENT_ITEM_TYPE);
2713892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (mimeTypeId == -1) {
2714892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            return;
2715892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
2716892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2717892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        String mCountryIso = getCountryIso();
2718892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        Cursor cursor = db.rawQuery(
2719892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    "SELECT _id, " + Phone.RAW_CONTACT_ID + ", " + Phone.NUMBER +
2720892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    " FROM " + Tables.DATA +
2721892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId
2722892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                            + " AND " + Phone.NUMBER + " NOT NULL", null);
2723892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2724892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        ContentValues phoneValues = new ContentValues();
2725892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        try {
2726892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            while (cursor.moveToNext()) {
2727892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                long dataID = cursor.getLong(0);
2728892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                long rawContactID = cursor.getLong(1);
2729892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String number = cursor.getString(2);
2730892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String numberE164 = PhoneNumberUtils.formatNumberToE164(number, mCountryIso);
2731892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                String normalizedNumber = PhoneNumberUtils.normalizeNumber(number);
2732892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                if (!TextUtils.isEmpty(normalizedNumber)) {
2733892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.clear();
2734892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactID);
2735892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.DATA_ID, dataID);
2736892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber);
2737892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    phoneValues.put(PhoneLookupColumns.MIN_MATCH,
2738892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                            PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber));
2739892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    db.insert(Tables.PHONE_LOOKUP, null, phoneValues);
2740892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
2741892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    if (numberE164 != null && !numberE164.equals(normalizedNumber)) {
2742892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, numberE164);
2743892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        phoneValues.put(PhoneLookupColumns.MIN_MATCH,
2744892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                                PhoneNumberUtils.toCallerIDMinMatch(numberE164));
2745892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                        db.insert(Tables.PHONE_LOOKUP, null, phoneValues);
2746892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                    }
2747892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                }
2748892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
2749892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        } finally {
2750892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            cursor.close();
2751892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
2752892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    }
2753892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
27542530512f639c4979fd7371c7dd25dd67e8118124Bai Tao    private void upgradeToVersion406(SQLiteDatabase db) {
27552530512f639c4979fd7371c7dd25dd67e8118124Bai Tao        db.execSQL("ALTER TABLE calls ADD countryiso TEXT;");
27562530512f639c4979fd7371c7dd25dd67e8118124Bai Tao    }
27572530512f639c4979fd7371c7dd25dd67e8118124Bai Tao
2758d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    private void upgradeToVersion409(SQLiteDatabase db) {
2759d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
2760d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        createDirectoriesTable(db);
2761d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    }
2762d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov
2763385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    /**
2764d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov     * Adding DEFAULT_DIRECTORY table.
2765385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     */
2766d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov    private void upgradeToVersion411(SQLiteDatabase db) {
2767d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS " + Tables.DEFAULT_DIRECTORY);
2768385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.DEFAULT_DIRECTORY + " (" +
2769385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                Contacts._ID + " INTEGER PRIMARY KEY" +
2770385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        ");");
2771385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2772385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // Process contacts without an account
2773385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
2774385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " SELECT " + RawContacts.CONTACT_ID +
2775385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS +
2776385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL " +
2777385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL ");
2778385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2779385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // Process accounts that don't have a default group (e.g. Exchange)
2780385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
2781385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " SELECT " + RawContacts.CONTACT_ID +
2782385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS +
2783385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE NOT EXISTS" +
2784385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " (SELECT " + Groups._ID +
2785385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "  FROM " + Tables.GROUPS +
2786385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
2787385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_NAME +
2788385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "    AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
2789385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
2790385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "    AND " + Groups.AUTO_ADD + " != 0" +
2791385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ")");
2792385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2793385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        long mimetype = lookupMimeTypeId(db, GroupMembership.CONTENT_ITEM_TYPE);
2794385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2795d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        // Process accounts that do have a default group (e.g. Google)
2796385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY +
2797385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " SELECT " + RawContacts.CONTACT_ID +
2798385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " FROM " + Tables.RAW_CONTACTS +
2799385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " JOIN " + Tables.DATA +
2800385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "   ON (" + RawContactsColumns.CONCRETE_ID + "=" + Data.RAW_CONTACT_ID + ")" +
2801385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                " WHERE " + DataColumns.MIMETYPE_ID + "=" + mimetype +
2802d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                " AND EXISTS" +
2803d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                " (SELECT " + Groups._ID +
2804d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "  FROM " + Tables.GROUPS +
2805d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
2806d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_NAME +
2807d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "    AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
2808d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                        + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
2809d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                "    AND " + Groups.AUTO_ADD + " != 0" +
2810d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov                ")");
28113d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
2812385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
2813e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    private void upgradeToVersion413(SQLiteDatabase db) {
28143ea7932a47027c8629d3a301e1a16e7d2c8a298dDmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS directories;");
28153ea7932a47027c8629d3a301e1a16e7d2c8a298dDmitri Plotnikov        createDirectoriesTable(db);
2816e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov    }
2817e0e24418cba10a5184e2966aaa32d5458fa6a387Dmitri Plotnikov
2818c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov    private void upgradeToVersion415(SQLiteDatabase db) {
2819c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        db.execSQL(
2820c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "ALTER TABLE " + Tables.GROUPS +
2821c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                " ADD " + Groups.GROUP_IS_READ_ONLY + " INTEGER NOT NULL DEFAULT 0");
2822c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov        db.execSQL(
2823c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "UPDATE " + Tables.GROUPS +
2824c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                "   SET " + Groups.GROUP_IS_READ_ONLY + "=1" +
2825c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov                " WHERE " + Groups.SYSTEM_ID + " NOT NULL");
2826c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov    }
2827c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov
2828b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    public String extractHandleFromEmailAddress(String email) {
2829b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email);
2830b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (tokens.length == 0) {
2831b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return null;
2832b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2833b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
2834b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        String address = tokens[0].getAddress();
2835b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        int at = address.indexOf('@');
2836b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        if (at != -1) {
2837b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return address.substring(0, at);
2838b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2839b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        return null;
2840b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2841b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
284208768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov    public String extractAddressFromEmailAddress(String email) {
284308768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email);
284408768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        if (tokens.length == 0) {
284508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov            return null;
284608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        }
284708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
284808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov        return tokens[0].getAddress();
284908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov    }
285008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov
2851b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    private long lookupMimeTypeId(SQLiteDatabase db, String mimeType) {
2852b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        try {
2853b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return DatabaseUtils.longForQuery(db,
2854b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    "SELECT " + MimetypesColumns._ID +
2855b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    " FROM " + Tables.MIMETYPES +
2856b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                    " WHERE " + MimetypesColumns.MIMETYPE
2857b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov                            + "='" + mimeType + "'", null);
2858b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        } catch (SQLiteDoneException e) {
2859b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            // No rows of this type in the database
2860b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov            return -1;
2861b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov        }
2862b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov    }
2863b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov
28645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void bindString(SQLiteStatement stmt, int index, String value) {
28655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        if (value == null) {
28665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            stmt.bindNull(index);
28675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        } else {
28685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            stmt.bindString(index, value);
28695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov        }
28705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    }
28715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov
287278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    private void bindLong(SQLiteStatement stmt, int index, Number value) {
287378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (value == null) {
287478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            stmt.bindNull(index);
287578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        } else {
287678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            stmt.bindLong(index, value.longValue());
287778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
287878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
287978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
2880a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    /**
2881f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * Adds index stats into the SQLite database to force it to always use the lookup indexes.
2882f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     */
2883f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    private void updateSqliteStats(SQLiteDatabase db) {
2884f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2885f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        // Specific stats strings are based on an actual large database after running ANALYZE
2886f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        try {
28878fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.CONTACTS,
28888fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "contacts_restricted_index", "10000 9000");
28898fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.CONTACTS,
28908fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "contacts_has_phone_index", "10000 500");
28918fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
28928fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.RAW_CONTACTS,
28938fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "raw_contacts_source_id_index", "10000 1 1 1");
28948fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.RAW_CONTACTS,
28958fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "raw_contacts_contact_id_index", "10000 2");
28968fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
28978fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
28988fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "name_lookup_raw_contact_id_index", "10000 3");
28998fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
2900916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov                    "name_lookup_index", "10000 3 2 2 1");
29018fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NAME_LOOKUP,
29028fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "sqlite_autoindex_name_lookup_1", "10000 3 2 1");
29038fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
29048fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.PHONE_LOOKUP,
29058fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "phone_lookup_index", "10000 2 2 1");
290636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov            updateIndexStats(db, Tables.PHONE_LOOKUP,
290736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov                    "phone_lookup_min_match_index", "10000 2 2 1");
29088fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
29098fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.DATA,
29108fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "data_mimetype_data1_index", "60000 5000 2");
29118fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.DATA,
29128fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "data_raw_contact_id", "60000 10");
29138fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
29148fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.GROUPS,
29158fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "groups_source_id_index", "50 1 1 1");
29168fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
29178fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov            updateIndexStats(db, Tables.NICKNAME_LOOKUP,
29188fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov                    "sqlite_autoindex_name_lookup_1", "500 2 1");
29198fddc066662d58e8d6a436decb8dafbf28ce652eDmitri Plotnikov
2920f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        } catch (SQLException e) {
2921f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            Log.e(TAG, "Could not update index stats", e);
2922f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        }
2923f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2924f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2925f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    /**
2926f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * Stores statistics for a given index.
2927f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     *
2928f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * @param stats has the following structure: the first index is the expected size of
2929f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * the table.  The following integer(s) are the expected number of records selected with the
2930f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     * index.  There should be one integer per indexed column.
2931f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov     */
29325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov    private void updateIndexStats(SQLiteDatabase db, String table, String index,
29335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov            String stats) {
2934f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        db.execSQL("DELETE FROM sqlite_stat1 WHERE tbl='" + table + "' AND idx='" + index + "';");
2935f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        db.execSQL("INSERT INTO sqlite_stat1 (tbl,idx,stat)"
2936f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov                + " VALUES ('" + table + "','" + index + "','" + stats + "');");
2937f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2938f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2939f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    @Override
2940f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    public synchronized SQLiteDatabase getWritableDatabase() {
2941f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        SQLiteDatabase db = super.getWritableDatabase();
2942f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        if (mReopenDatabase) {
2943f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            mReopenDatabase = false;
2944f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            close();
2945f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov            db = super.getWritableDatabase();
2946f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        }
2947f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov        return db;
2948f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    }
2949f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov
2950f79538095a1af16dcd6e641448b627f60f197802Dmitri Plotnikov    /**
2951a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov     * Wipes all data except mime type and package lookup tables.
2952a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov     */
2953a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    public void wipeData() {
2954a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
29553d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov
295633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.ACCOUNTS + ";");
295769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " VALUES(NULL, NULL)");
295833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov
2959d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CONTACTS + ";");
29605ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.RAW_CONTACTS + ";");
2961a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.DATA + ";");
2962a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.PHONE_LOOKUP + ";");
2963a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NAME_LOOKUP + ";");
2964ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("DELETE FROM " + Tables.GROUPS + ";");
2965b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.AGGREGATION_EXCEPTIONS + ";");
2966eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey        db.execSQL("DELETE FROM " + Tables.SETTINGS + ";");
2967a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.ACTIVITIES + ";");
29683d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CALLS + ";");
296972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.DIRECTORIES + ";");
297072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov
2971b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        // Note: we are not removing reference data from Tables.NICKNAME_LOOKUP
2972a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
2973b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
297404b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    public NameSplitter createNameSplitter() {
297504b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov        return new NameSplitter(
297604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_prefixes),
297704b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_last_name_prefixes),
297804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_suffixes),
297904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                mContext.getString(com.android.internal.R.string.common_name_conjunctions),
298004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov                Locale.getDefault());
298104b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov    }
298204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov
2983b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
2984619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey     * Return the {@link ApplicationInfo#uid} for the given package name.
2985619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey     */
2986619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    public static int getUidForPackageName(PackageManager pm, String packageName) {
2987619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        try {
2988619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            ApplicationInfo clientInfo = pm.getApplicationInfo(packageName, 0 /* no flags */);
2989619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            return clientInfo.uid;
2990619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        } catch (NameNotFoundException e) {
2991619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            throw new RuntimeException(e);
2992619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        }
2993619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
2994619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
2995619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    /**
2996b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Perform an internal string-to-integer lookup using the compiled
2997b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * {@link SQLiteStatement} provided, using the in-memory cache to speed up
2998b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups. If a mapping isn't found in cache or database, it will be
2999b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * created. All new, uncached answers are added to the cache automatically.
3000b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *
3001b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param query Compiled statement used to query for the mapping.
3002b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param insert Compiled statement used to insert a new mapping when no
3003b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *            existing one is found in cache or from query.
3004b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param value Value to find mapping for.
3005b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param cache In-memory cache of previous answers.
3006b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @return An unique integer mapping for the given value.
3007b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3008f4a3b7e523e36679b68edd2af632e26648758ff2Dmitri Plotnikov    private long getCachedId(SQLiteStatement query, SQLiteStatement insert,
3009b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String value, HashMap<String, Long> cache) {
3010b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Try an in-memory cache lookup
3011b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (cache.containsKey(value)) {
3012b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return cache.get(value);
3013b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3014b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3015b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        long id = -1;
3016b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
3017b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try searching database for mapping
3018b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(query, 1, value);
3019b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            id = query.simpleQueryForLong();
3020b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
3021b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Nothing found, so try inserting new mapping
3022b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(insert, 1, value);
3023b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            id = insert.executeInsert();
3024b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3025b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3026b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (id != -1) {
3027b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Cache and return the new answer
3028b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            cache.put(value, id);
3029b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return id;
3030b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } else {
3031b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Otherwise throw if no mapping found or created
3032b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            throw new IllegalStateException("Couldn't find or create internal "
3033b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                    + "lookup table entry for value " + value);
3034b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3035b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3036b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3037b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3038ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Convert a package name into an integer, using {@link Tables#PACKAGES} for
3039b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
3040b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3041b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getPackageId(String packageName) {
304278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mPackageQuery == null) {
304378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mPackageQuery = getWritableDatabase().compileStatement(
304478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + PackagesColumns._ID +
304578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.PACKAGES +
304678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + PackagesColumns.PACKAGE + "=?");
304778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
304878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
304978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mPackageInsert == null) {
305078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mPackageInsert = getWritableDatabase().compileStatement(
305178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT INTO " + Tables.PACKAGES + "("
305278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + PackagesColumns.PACKAGE +
305378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    ") VALUES (?)");
305478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3055b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return getCachedId(mPackageQuery, mPackageInsert, packageName, mPackageCache);
3056b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3057b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3058b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3059ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Convert a mimetype into an integer, using {@link Tables#MIMETYPES} for
3060b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
3061b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3062b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getMimeTypeId(String mimetype) {
3063b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return getCachedId(mMimetypeQuery, mMimetypeInsert, mimetype, mMimetypeCache);
3064b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3065b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
30662a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForStructuredName() {
30672a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdStructuredName;
30682a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
30692a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
30702a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForOrganization() {
30712a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdOrganization;
30722a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
30732a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
30742a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForIm() {
30752a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdIm;
30762a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
30772a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
30782a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public long getMimeTypeIdForEmail() {
30792a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        return mMimeTypeIdEmail;
30802a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
30812a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
30822a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    public int getDisplayNameSourceForMimeTypeId(int mimeTypeId) {
30832a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        if (mimeTypeId == mMimeTypeIdStructuredName) {
30842a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.STRUCTURED_NAME;
30852a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdEmail) {
30862a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.EMAIL;
30872a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdPhone) {
30882a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.PHONE;
30892a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdOrganization) {
30902a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.ORGANIZATION;
30912a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else if (mimeTypeId == mMimeTypeIdNickname) {
30922a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.NICKNAME;
30932a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        } else {
30942a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov            return DisplayNameSources.UNDEFINED;
30952a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov        }
30962a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov    }
30972a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov
3098b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3099ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Find the mimetype for the given {@link Data#_ID}.
3100b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3101b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getDataMimeType(long dataId) {
310278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mDataMimetypeQuery == null) {
310378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mDataMimetypeQuery = getWritableDatabase().compileStatement(
310478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + MimetypesColumns.MIMETYPE +
310578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.DATA_JOIN_MIMETYPES +
310678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + Tables.DATA + "." + Data._ID + "=?");
310778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3108b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
3109b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
3110b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mDataMimetypeQuery, 1, dataId);
3111b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mDataMimetypeQuery.simpleQueryForString();
3112b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
3113b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
3114b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
3115b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
3116b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3117b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
3118b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
3119b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
3120b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Find the mime-type for the given {@link Activities#_ID}.
3121b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
3122b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getActivityMimeType(long activityId) {
312378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mActivitiesMimetypeQuery == null) {
312478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mActivitiesMimetypeQuery = getWritableDatabase().compileStatement(
312578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + MimetypesColumns.MIMETYPE +
312678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.ACTIVITIES_JOIN_MIMETYPES +
312778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + Tables.ACTIVITIES + "." + Activities._ID + "=?");
312878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3129b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
3130b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
3131b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mActivitiesMimetypeQuery, 1, activityId);
3132b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mActivitiesMimetypeQuery.simpleQueryForString();
3133b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
3134b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
3135b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
3136b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
3137b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
3138b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
31396bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov
31406bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov    /**
3141d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Update {@link Contacts#IN_VISIBLE_GROUP} for all contacts.
3142ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     */
3143ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public void updateAllVisible() {
3144385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        updateCustomContactVisibility(getWritableDatabase(), "");
3145ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
3146ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
3147ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    /**
3148f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov     * Updates contact visibility and return true iff the visibility was actually changed.
3149f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov     */
3150f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    public boolean updateContactVisibleOnlyIfChanged(long contactId) {
3151f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        return updateContactVisible(contactId, true);
3152f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    }
3153f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
3154f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    /**
3155385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     * Update {@link Contacts#IN_VISIBLE_GROUP} and
3156385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov     * {@link Tables#DEFAULT_DIRECTORY} for a specific contact.
3157ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     */
3158fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov    public void updateContactVisible(long contactId) {
3159f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        updateContactVisible(contactId, false);
3160f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    }
3161f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
3162f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    public boolean updateContactVisible(long contactId, boolean onlyIfChanged) {
31634394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
3164f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        updateCustomContactVisibility(db, " AND " + Contacts._ID + "=" + contactId);
3165385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3166385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        String contactIdAsString = String.valueOf(contactId);
3167385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        long mimetype = getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
3168385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3169385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // The contact will be included in the default directory if contains
3170d6ef718d85724dc482dc88f8c8a87b356e63c0f6Dmitri Plotnikov        // a raw contact that is in any group or in an account that
3171385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        // does not have any AUTO_ADD groups.
3172f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        boolean newVisibility = DatabaseUtils.longForQuery(db,
3173385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                "SELECT EXISTS (" +
3174385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts.CONTACT_ID +
3175385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3176385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " JOIN " + Tables.DATA +
3177385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   ON (" + RawContactsColumns.CONCRETE_ID + "="
3178385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                            + Data.RAW_CONTACT_ID + ")" +
3179385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3180385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + DataColumns.MIMETYPE_ID + "=?" +
3181385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ") OR EXISTS (" +
3182385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts._ID +
3183385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3184385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3185385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND NOT EXISTS" +
3186385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        " (SELECT " + Groups._ID +
3187385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  FROM " + Tables.GROUPS +
3188385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  WHERE " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " = "
3189385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                                + GroupsColumns.CONCRETE_ACCOUNT_NAME +
3190385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " = "
3191385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                                + GroupsColumns.CONCRETE_ACCOUNT_TYPE +
3192385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        "  AND " + Groups.AUTO_ADD + " != 0" +
3193385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                        ")" +
3194385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ") OR EXISTS (" +
3195385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "SELECT " + RawContacts._ID +
3196385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
3197385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=?" +
3198385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL " +
3199385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    "   AND " + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL" +
3200385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                ")",
3201385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                new String[] {
3202385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    contactIdAsString,
32036c47e208236a62c55f396116e087331e05e148f3Dmitri Plotnikov                    String.valueOf(mimetype),
3204385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    contactIdAsString,
32056c47e208236a62c55f396116e087331e05e148f3Dmitri Plotnikov                    contactIdAsString
3206f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                }) != 0;
3207385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov
3208f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        if (onlyIfChanged) {
3209f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov            boolean oldVisibility = isContactInDefaultDirectory(db, contactId);
3210f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov            if (oldVisibility == newVisibility) {
3211f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                return false;
3212f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov            }
3213f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        }
3214f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
3215f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        if (newVisibility) {
3216385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            db.execSQL("INSERT OR IGNORE INTO " + Tables.DEFAULT_DIRECTORY + " VALUES(?)",
3217385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    new String[] { contactIdAsString });
3218385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        } else {
3219385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov            db.execSQL("DELETE FROM " + Tables.DEFAULT_DIRECTORY + " WHERE " + Contacts._ID + "=?",
3220385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov                    new String[] { contactIdAsString });
3221385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov        }
3222f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        return true;
3223f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    }
3224f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov
3225f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov    public boolean isContactInDefaultDirectory(SQLiteDatabase db, long contactId) {
3226f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        if (mContactInDefaultDirectoryQuery == null) {
3227f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov            mContactInDefaultDirectoryQuery = db.compileStatement(
3228f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                    "SELECT EXISTS (" +
3229f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                            "SELECT 1 FROM " + Tables.DEFAULT_DIRECTORY +
3230f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov                            " WHERE " + Contacts._ID + "=?)");
3231f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        }
3232f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        mContactInDefaultDirectoryQuery.bindLong(1, contactId);
3233f266e8c568905337960b1fec5379841585af92a7Dmitri Plotnikov        return mContactInDefaultDirectoryQuery.simpleQueryForLong() != 0;
3234385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    }
32354394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
3236385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov    private void updateCustomContactVisibility(SQLiteDatabase db, String selection) {
3237ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        final long groupMembershipMimetypeId = getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
32384394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        String[] selectionArgs = new String[]{String.valueOf(groupMembershipMimetypeId)};
32394394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov
32404394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // First delete what needs to be deleted, then insert what needs to be added.
32414394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // Since flash writes are very expensive, this approach is much better than
32424394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        // delete-all-insert-all.
32434394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.VISIBLE_CONTACTS +
32444394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " WHERE " + "_id NOT IN" +
32454394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        "(SELECT " + Contacts._ID +
32464394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        " FROM " + Tables.CONTACTS +
32474394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                        " WHERE (" + Clauses.CONTACT_IS_VISIBLE + ")=1) " + selection,
32484394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                selectionArgs);
3249fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov
32504394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov        db.execSQL("INSERT INTO " + Tables.VISIBLE_CONTACTS +
32514394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " SELECT " + Contacts._ID +
32524394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " FROM " + Tables.CONTACTS +
32534394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " WHERE " + Contacts._ID +
32544394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                   " NOT IN " + Tables.VISIBLE_CONTACTS +
32554394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                           " AND (" + Clauses.CONTACT_IS_VISIBLE + ")=1 " + selection,
32564394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov                selectionArgs);
3257ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
3258ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
3259ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    /**
3260d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Returns contact ID for the given contact or zero if it is NULL.
32616bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov     */
3262d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    public long getContactId(long rawContactId) {
326378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mContactIdQuery == null) {
326478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mContactIdQuery = getWritableDatabase().compileStatement(
326578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + RawContacts.CONTACT_ID +
326678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
326778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts._ID + "=?");
326878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
32696bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        try {
3270d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov            DatabaseUtils.bindObjectToProgram(mContactIdQuery, 1, rawContactId);
3271d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov            return mContactIdQuery.simpleQueryForLong();
32726bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        } catch (SQLiteDoneException e) {
3273a3bd0246ca3741877488bca7aadd91c79b2fd8d2Fred Quintana            // No valid mapping found, so return 0
32746bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov            return 0;
32756bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        }
32766bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov    }
327761bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov
32785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov    public int getAggregationMode(long rawContactId) {
327978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mAggregationModeQuery == null) {
328078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mAggregationModeQuery = getWritableDatabase().compileStatement(
328178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "SELECT " + RawContacts.AGGREGATION_MODE +
328278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " FROM " + Tables.RAW_CONTACTS +
328378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts._ID + "=?");
328478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
3285f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        try {
32865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov            DatabaseUtils.bindObjectToProgram(mAggregationModeQuery, 1, rawContactId);
3287f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            return (int)mAggregationModeQuery.simpleQueryForLong();
3288f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        } catch (SQLiteDoneException e) {
32896cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov            // No valid row found, so return "disabled"
32906cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov            return RawContacts.AGGREGATION_MODE_DISABLED;
3291f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3292f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3293f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
3294892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    public void buildPhoneLookupAndContactQuery(
3295892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            SQLiteQueryBuilder qb, String normalizedNumber, String numberE164) {
3296892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        String minMatch = PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber);
3297e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        StringBuilder sb = new StringBuilder();
329836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        appendPhoneLookupTables(sb, minMatch, true);
3299e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        qb.setTables(sb.toString());
3300e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
3301e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb = new StringBuilder();
3302892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        appendPhoneLookupSelection(sb, normalizedNumber, numberE164);
3303e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        qb.appendWhere(sb.toString());
3304bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    }
3305bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
3306e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    public String buildPhoneLookupAsNestedQuery(String number) {
3307e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        StringBuilder sb = new StringBuilder();
330836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        final String minMatch = PhoneNumberUtils.toCallerIDMinMatch(number);
3309e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append("(SELECT DISTINCT raw_contact_id" + " FROM ");
331036045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        appendPhoneLookupTables(sb, minMatch, false);
3311e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(" WHERE ");
3312892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        appendPhoneLookupSelection(sb, number, null);
3313e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(")");
3314e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        return sb.toString();
3315e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    }
3316e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
331736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    private void appendPhoneLookupTables(StringBuilder sb, final String minMatch,
3318e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov            boolean joinContacts) {
3319e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        sb.append(Tables.RAW_CONTACTS);
3320e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        if (joinContacts) {
3321fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov            sb.append(" JOIN " + getContactView() + " contacts_view"
3322fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov                    + " ON (contacts_view._id = raw_contacts.contact_id)");
3323e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov        }
3324892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        sb.append(", (SELECT data_id, normalized_number, length(normalized_number) as len "
3325892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + " FROM phone_lookup " + " WHERE (" + Tables.PHONE_LOOKUP + "."
3326892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                + PhoneLookupColumns.MIN_MATCH + " = '");
332736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        sb.append(minMatch);
332836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        sb.append("')) AS lookup, " + Tables.DATA);
3329e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov    }
3330e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov
3331892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    private void appendPhoneLookupSelection(StringBuilder sb, String number, String numberE164) {
3332892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        sb.append("lookup.data_id=data._id AND data.raw_contact_id=raw_contacts._id");
3333892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        boolean hasNumberE164 = !TextUtils.isEmpty(numberE164);
3334892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        boolean hasNumber = !TextUtils.isEmpty(number);
3335892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        if (hasNumberE164 || hasNumber) {
3336892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            sb.append(" AND ( ");
3337892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumberE164) {
3338892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" lookup.normalized_number = ");
3339892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                DatabaseUtils.appendEscapedSQLString(sb, numberE164);
3340892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3341892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumberE164 && hasNumber) {
3342892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" OR ");
3343892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3344892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            if (hasNumber) {
3345892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                int numberLen = number.length();
3346892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" lookup.len <= ");
3347892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(numberLen);
3348892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" AND substr(");
3349892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                DatabaseUtils.appendEscapedSQLString(sb, number);
3350892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(',');
3351892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(numberLen);
3352892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov                sb.append(" - lookup.len + 1) = lookup.normalized_number");
3353892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            }
3354892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            sb.append(')');
3355892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        }
335636045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    }
335736045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov
335836045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov    public String getUseStrictPhoneNumberComparisonParameter() {
335936045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov        return mUseStrictPhoneNumberComparison ? "1" : "0";
3360fb362d1a5df250a49fad06db323b0d41fe0e3757Dmitri Plotnikov    }
3361bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
3362619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    /**
3363b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     * Loads common nickname mappings into the database.
3364b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     */
3365b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private void loadNicknameLookupTable(SQLiteDatabase db) {
336651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NICKNAME_LOOKUP);
336751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
336828f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar        String[] strings = mContext.getResources().getStringArray(
336928f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar                com.android.internal.R.array.common_nicknames);
3370b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        if (strings == null || strings.length == 0) {
3371b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            return;
3372b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
3373b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
3374b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        SQLiteStatement nicknameLookupInsert = db.compileStatement("INSERT INTO "
3375b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                + Tables.NICKNAME_LOOKUP + "(" + NicknameLookupColumns.NAME + ","
3376b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                + NicknameLookupColumns.CLUSTER + ") VALUES (?,?)");
3377b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
337851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        try {
337951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            for (int clusterId = 0; clusterId < strings.length; clusterId++) {
338051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                String[] names = strings[clusterId].split(",");
338151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                for (int j = 0; j < names.length; j++) {
338251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    String name = NameNormalizer.normalize(names[j]);
338351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    try {
338451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        DatabaseUtils.bindObjectToProgram(nicknameLookupInsert, 1, name);
338551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        DatabaseUtils.bindObjectToProgram(nicknameLookupInsert, 2,
338651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                                String.valueOf(clusterId));
338751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        nicknameLookupInsert.executeInsert();
338851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    } catch (SQLiteException e) {
338951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov
339051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        // Print the exception and keep going - this is not a fatal error
339151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                        Log.e(TAG, "Cannot insert nickname: " + names[j], e);
339251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov                    }
3393b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                }
3394b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            }
339551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov        } finally {
339651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov            nicknameLookupInsert.close();
3397b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
3398b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    }
3399b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
3400f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    public static void copyStringValue(ContentValues toValues, String toKey,
3401f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            ContentValues fromValues, String fromKey) {
3402f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        if (fromValues.containsKey(fromKey)) {
3403f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            toValues.put(toKey, fromValues.getAsString(fromKey));
3404f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3405f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3406f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
3407f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    public static void copyLongValue(ContentValues toValues, String toKey,
3408f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            ContentValues fromValues, String fromKey) {
3409f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        if (fromValues.containsKey(fromKey)) {
3410f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            long longValue;
3411f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            Object value = fromValues.get(fromKey);
3412f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            if (value instanceof Boolean) {
3413f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                if ((Boolean)value) {
3414f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                    longValue = 1;
3415f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                } else {
3416f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                    longValue = 0;
3417f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                }
34181b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov            } else if (value instanceof String) {
34191b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov                longValue = Long.parseLong((String)value);
3420f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            } else {
34211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov                longValue = ((Number)value).longValue();
3422f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            }
3423f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            toValues.put(toKey, longValue);
3424f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
3425f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
3426f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
342735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    public SyncStateContentProviderHelper getSyncState() {
342835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        return mSyncState;
342935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    }
3430c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3431c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    /**
3432c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     * Delete the aggregate contact if it has no constituent raw contacts other
3433c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     * than the supplied one.
3434c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     */
3435c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    public void removeContactIfSingleton(long rawContactId) {
3436c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
3437c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3438c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        // Obtain contact ID from the supplied raw contact ID
3439c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        String contactIdFromRawContactId = "(SELECT " + RawContacts.CONTACT_ID + " FROM "
3440c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=" + rawContactId + ")";
3441c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3442c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        // Find other raw contacts in the same aggregate contact
3443c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        String otherRawContacts = "(SELECT contacts1." + RawContacts._ID + " FROM "
3444c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + Tables.RAW_CONTACTS + " contacts1 JOIN " + Tables.RAW_CONTACTS + " contacts2 ON ("
3445c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "contacts1." + RawContacts.CONTACT_ID + "=contacts2." + RawContacts.CONTACT_ID
3446c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + ") WHERE contacts1." + RawContacts._ID + "!=" + rawContactId + ""
3447c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " AND contacts2." + RawContacts._ID + "=" + rawContactId + ")";
3448c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
3449c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CONTACTS
3450c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " WHERE " + Contacts._ID + "=" + contactIdFromRawContactId
3451c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " AND NOT EXISTS " + otherRawContacts + ";");
3452c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    }
34534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
34544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    /**
3455b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     * Returns the value from the {@link Tables#PROPERTIES} table.
3456b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     */
3457b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public String getProperty(String key, String defaultValue) {
3458b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        Cursor cursor = getReadableDatabase().query(Tables.PROPERTIES,
3459b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                new String[]{PropertiesColumns.PROPERTY_VALUE},
3460b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                PropertiesColumns.PROPERTY_KEY + "=?",
3461b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                new String[]{key}, null, null, null);
3462b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        String value = null;
3463b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        try {
3464b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            if (cursor.moveToFirst()) {
3465b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov                value = cursor.getString(0);
3466b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            }
3467b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        } finally {
3468b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov            cursor.close();
3469b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        }
3470b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3471b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        return value != null ? value : defaultValue;
3472b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
3473b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3474b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    /**
3475b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     * Stores a key-value pair in the {@link Tables#PROPERTIES} table.
3476b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov     */
3477b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    public void setProperty(String key, String value) {
34783d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        setProperty(getWritableDatabase(), key, value);
34793d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    }
34803d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov
34813d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov    private void setProperty(SQLiteDatabase db, String key, String value) {
3482b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        ContentValues values = new ContentValues();
3483b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        values.put(PropertiesColumns.PROPERTY_KEY, key);
3484b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov        values.put(PropertiesColumns.PROPERTY_VALUE, value);
34853d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov        db.replace(Tables.PROPERTIES, null, values);
3486b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    }
3487b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov
3488b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov    /**
34894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     * Check if {@link Binder#getCallingUid()} should be allowed access to
34904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     * {@link RawContacts#IS_RESTRICTED} data.
34914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov     */
3492d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    boolean hasAccessToRestrictedData() {
34934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        final PackageManager pm = mContext.getPackageManager();
34946ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        int caller = Binder.getCallingUid();
34956ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        if (caller == 0) return true; // root can do anything
34966ff43a7545880f0b1c0f0a82b3551fb1d0dfa956Marco Nelissen        final String[] callerPackages = pm.getPackagesForUid(caller);
34974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
34984a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        // Has restricted access if caller matches any packages
34994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        for (String callerPackage : callerPackages) {
3500d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton            if (hasAccessToRestrictedData(callerPackage)) {
3501763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                return true;
3502763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar            }
3503763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        }
3504763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return false;
3505763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    }
3506763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar
3507763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    /**
3508763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     * Check if requestingPackage should be allowed access to
3509763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     * {@link RawContacts#IS_RESTRICTED} data.
3510763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar     */
3511d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton    boolean hasAccessToRestrictedData(String requestingPackage) {
3512d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        if (mUnrestrictedPackages != null) {
3513d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton            for (String allowedPackage : mUnrestrictedPackages) {
3514d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                if (allowedPackage.equals(requestingPackage)) {
3515d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                    return true;
3516d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton                }
35174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov            }
35184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        }
35194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov        return false;
35204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
35214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
35224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getDataView() {
3523d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa        return getDataView(false);
3524d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3525d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3526d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    public String getDataView(boolean requireRestrictedView) {
3527d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3528d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa                Views.DATA_ALL : Views.DATA_RESTRICTED;
35294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
35304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
35314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getRawContactView() {
3532763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return getRawContactView(false);
3533763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    }
3534763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar
3535763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    public String getRawContactView(boolean requireRestrictedView) {
3536d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3537763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                Views.RAW_CONTACTS_ALL : Views.RAW_CONTACTS_RESTRICTED;
35384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
35394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
35404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    public String getContactView() {
3541763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar        return getContactView(false);
35424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
35434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov
3544763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar    public String getContactView(boolean requireRestrictedView) {
3545d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3546763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar                Views.CONTACTS_ALL : Views.CONTACTS_RESTRICTED;
3547f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey    }
3548f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey
354989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov    public String getGroupView() {
355089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov        return Views.GROUPS_ALL;
355189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov    }
355289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov
3553a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getRawEntitiesView() {
3554a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return getRawEntitiesView(false);
3555a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    }
3556a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
3557a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getRawEntitiesView(boolean requireRestrictedView) {
3558a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3559a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                Views.RAW_ENTITIES : Views.RAW_ENTITIES_RESTRICTED;
3560a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    }
3561a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov
3562a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getEntitiesView() {
3563a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov        return getEntitiesView(false);
3564d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3565d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3566a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov    public String getEntitiesView(boolean requireRestrictedView) {
3567d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton        return (hasAccessToRestrictedData() && !requireRestrictedView) ?
3568a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov                Views.ENTITIES : Views.ENTITIES_RESTRICTED;
3569d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa    }
3570d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa
3571ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov    /**
3572ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov     * Test if any of the columns appear in the given projection.
3573ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov     */
3574ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov    public boolean isInProjection(String[] projection, String... columns) {
357582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        if (projection == null) {
357682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            return true;
357782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        }
3578ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov
357982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        // Optimized for a single-column test
358082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        if (columns.length == 1) {
358182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            String column = columns[0];
358282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            for (String test : projection) {
358382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                if (column.equals(test)) {
358482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                    return true;
358582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                }
358682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            }
358782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov        } else {
358882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov            for (String test : projection) {
358982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov                for (String column : columns) {
3590ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                    if (column.equals(test)) {
3591ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                        return true;
3592ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                    }
3593ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov                }
3594ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov            }
3595ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov        }
3596ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov        return false;
35974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov    }
3598fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3599fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    /**
3600fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * Returns a detailed exception message for the supplied URI.  It includes the calling
3601fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * user and calling package(s).
3602fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     */
3603fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    public String exceptionMessage(Uri uri) {
3604fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        return exceptionMessage(null, uri);
3605fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    }
3606fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3607fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    /**
3608fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * Returns a detailed exception message for the supplied URI.  It includes the calling
3609fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     * user and calling package(s).
3610fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov     */
3611fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    public String exceptionMessage(String message, Uri uri) {
3612fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        StringBuilder sb = new StringBuilder();
3613fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (message != null) {
3614fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(message).append("; ");
3615fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3616fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        sb.append("URI: ").append(uri);
3617fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        final PackageManager pm = mContext.getPackageManager();
3618fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        int callingUid = Binder.getCallingUid();
3619fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        sb.append(", calling user: ");
3620fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        String userName = pm.getNameForUid(callingUid);
3621fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (userName != null) {
3622fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(userName);
3623fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        } else {
3624fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            sb.append(callingUid);
3625fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3626fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3627fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        final String[] callerPackages = pm.getPackagesForUid(callingUid);
3628fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        if (callerPackages != null && callerPackages.length > 0) {
3629fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            if (callerPackages.length == 1) {
3630fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(", calling package:");
3631fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(callerPackages[0]);
3632fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            } else {
3633fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append(", calling package is one of: [");
3634fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                for (int i = 0; i < callerPackages.length; i++) {
3635fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    if (i != 0) {
3636fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                        sb.append(", ");
3637fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    }
3638fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                    sb.append(callerPackages[i]);
3639fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                }
3640fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov                sb.append("]");
3641fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov            }
3642fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        }
3643fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov
3644fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov        return sb.toString();
3645fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov    }
3646892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov
3647892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    protected String getCountryIso() {
3648892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        CountryDetector detector =
3649892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov            (CountryDetector) mContext.getSystemService(Context.COUNTRY_DETECTOR);
3650892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov        return detector.detectCountry().getCountryIso();
3651892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov    }
365278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
365378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void deleteStatusUpdate(long dataId) {
365478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mStatusUpdateDelete == null) {
365578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateDelete = getWritableDatabase().compileStatement(
365678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "DELETE FROM " + Tables.STATUS_UPDATES +
365778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + StatusUpdatesColumns.DATA_ID + "=?");
365878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
365978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateDelete.bindLong(1, dataId);
366078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateDelete.execute();
366178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
366278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
366378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void replaceStatusUpdate(Long dataId, long timestamp, String status, String resPackage,
366478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            Long iconResource, Integer labelResource) {
366578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mStatusUpdateReplace == null) {
366678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateReplace = getWritableDatabase().compileStatement(
366778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "("
366878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdatesColumns.DATA_ID + ", "
366978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_TIMESTAMP + ","
367078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS + ","
367178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_RES_PACKAGE + ","
367278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_ICON + ","
367378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_LABEL + ")" +
367478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " VALUES (?,?,?,?,?,?)");
367578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
367678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace.bindLong(1, dataId);
367778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace.bindLong(2, timestamp);
367878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mStatusUpdateReplace, 3, status);
367978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mStatusUpdateReplace, 4, resPackage);
368078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindLong(mStatusUpdateReplace, 5, iconResource);
368178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindLong(mStatusUpdateReplace, 6, labelResource);
368278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mStatusUpdateReplace.execute();
368378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
368478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
368578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void insertStatusUpdate(Long dataId, String status, String resPackage, Long iconResource,
368678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            Integer labelResource) {
368778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mStatusUpdateInsert == null) {
368878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateInsert = getWritableDatabase().compileStatement(
368978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT INTO " + Tables.STATUS_UPDATES + "("
369078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdatesColumns.DATA_ID + ", "
369178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS + ","
369278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_RES_PACKAGE + ","
369378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_ICON + ","
369478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + StatusUpdates.STATUS_LABEL + ")" +
369578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " VALUES (?,?,?,?,?)");
369678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
369778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        try {
369878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateInsert.bindLong(1, dataId);
369978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateInsert, 2, status);
370078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateInsert, 3, resPackage);
370178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusUpdateInsert, 4, iconResource);
370278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusUpdateInsert, 5, labelResource);
370378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateInsert.executeInsert();
370478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        } catch (SQLiteConstraintException e) {
370578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            // The row already exists - update it
370678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            if (mStatusUpdateAutoTimestamp == null) {
370778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                mStatusUpdateAutoTimestamp = getWritableDatabase().compileStatement(
370878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        "UPDATE " + Tables.STATUS_UPDATES +
370978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?,"
371078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + StatusUpdates.STATUS + "=?" +
371178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"
371278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + " AND " + StatusUpdates.STATUS + "!=?");
371378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            }
371478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
371578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            long timestamp = System.currentTimeMillis();
371678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateAutoTimestamp.bindLong(1, timestamp);
371778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateAutoTimestamp, 2, status);
371878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateAutoTimestamp.bindLong(3, dataId);
371978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusUpdateAutoTimestamp, 4, status);
372078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusUpdateAutoTimestamp.execute();
372178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
372278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            if (mStatusAttributionUpdate == null) {
372378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                mStatusAttributionUpdate = getWritableDatabase().compileStatement(
372478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        "UPDATE " + Tables.STATUS_UPDATES +
372578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?,"
372678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + StatusUpdates.STATUS_ICON + "=?,"
372778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                + StatusUpdates.STATUS_LABEL + "=?" +
372878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                        " WHERE " + StatusUpdatesColumns.DATA_ID + "=?");
372978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            }
373078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindString(mStatusAttributionUpdate, 1, resPackage);
373178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusAttributionUpdate, 2, iconResource);
373278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            bindLong(mStatusAttributionUpdate, 3, labelResource);
373378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusAttributionUpdate.bindLong(4, dataId);
373478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mStatusAttributionUpdate.execute();
373578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
373678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
373778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
373878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /**
373978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Resets the {@link RawContacts#NAME_VERIFIED} flag to 0 on all other raw
374078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * contacts in the same aggregate
374178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
374278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void resetNameVerifiedForOtherRawContacts(long rawContactId) {
374378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mResetNameVerifiedForOtherRawContacts == null) {
374478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mResetNameVerifiedForOtherRawContacts = getWritableDatabase().compileStatement(
374578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.RAW_CONTACTS +
374678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + RawContacts.NAME_VERIFIED + "=0" +
374778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts.CONTACT_ID + "=(" +
374878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            "SELECT " + RawContacts.CONTACT_ID +
374978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " FROM " + Tables.RAW_CONTACTS +
375078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " WHERE " + RawContacts._ID + "=?)" +
375178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " AND " + RawContacts._ID + "!=?");
375278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
375378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts.bindLong(1, rawContactId);
375478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts.bindLong(2, rawContactId);
375578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mResetNameVerifiedForOtherRawContacts.execute();
375678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
375778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
375878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void setDisplayName(long rawContactId, int displayNameSource,
375978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            String displayNamePrimary, String displayNameAlternative, String phoneticName,
376078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            int phoneticNameStyle, String sortKeyPrimary, String sortKeyAlternative) {
376178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mRawContactDisplayNameUpdate == null) {
376278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mRawContactDisplayNameUpdate = getWritableDatabase().compileStatement(
376378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.RAW_CONTACTS +
376478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " +
376578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.DISPLAY_NAME_SOURCE + "=?," +
376678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.DISPLAY_NAME_PRIMARY + "=?," +
376778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," +
376878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.PHONETIC_NAME + "=?," +
376978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.PHONETIC_NAME_STYLE + "=?," +
377078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.SORT_KEY_PRIMARY + "=?," +
377178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            RawContacts.SORT_KEY_ALTERNATIVE + "=?" +
377278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + RawContacts._ID + "=?");
377378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
377478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate.bindLong(1, displayNameSource);
377578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 2, displayNamePrimary);
377678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 3, displayNameAlternative);
377778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 4, phoneticName);
377878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate.bindLong(5, phoneticNameStyle);
377978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 6, sortKeyPrimary);
378078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mRawContactDisplayNameUpdate, 7, sortKeyAlternative);
378178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate.bindLong(8, rawContactId);
378278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mRawContactDisplayNameUpdate.execute();
378378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
378478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
378578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /*
378678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Sets the given dataId record in the "data" table to primary, and resets all data records of
378778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * the same mimetype and under the same contact to not be primary.
378878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     *
378978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * @param dataId the id of the data record to be set to primary. Pass -1 to clear the primary
379078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * flag of all data items of this raw contacts
379178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
379278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) {
379378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mSetPrimaryStatement == null) {
379478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mSetPrimaryStatement = getWritableDatabase().compileStatement(
379578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.DATA +
379678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + Data.IS_PRIMARY + "=(_id=?)" +
379778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=?" +
379878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "   AND " + Data.RAW_CONTACT_ID + "=?");
379978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
380078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.bindLong(1, dataId);
380178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.bindLong(2, mimeTypeId);
380278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.bindLong(3, rawContactId);
380378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetPrimaryStatement.execute();
380478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
380578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
380678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /*
380778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Clears the super primary of all data items of the given raw contact. does not touch
380878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * other raw contacts of the same joined aggregate
380978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
381078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void clearSuperPrimary(long rawContactId, long mimeTypeId) {
381178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mClearSuperPrimaryStatement == null) {
381278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mClearSuperPrimaryStatement = getWritableDatabase().compileStatement(
381378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.DATA +
381478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + Data.IS_SUPER_PRIMARY + "=0" +
381578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=?" +
381678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "   AND " + Data.RAW_CONTACT_ID + "=?");
381778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
381878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement.bindLong(1, mimeTypeId);
381978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement.bindLong(2, rawContactId);
382078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mClearSuperPrimaryStatement.execute();
382178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
382278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
382378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /*
382478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Sets the given dataId record in the "data" table to "super primary", and resets all data
382578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * records of the same mimetype and under the same aggregate to not be "super primary".
382678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     *
382778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * @param dataId the id of the data record to be set to primary.
382878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
382978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) {
383078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mSetSuperPrimaryStatement == null) {
383178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mSetSuperPrimaryStatement = getWritableDatabase().compileStatement(
383278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "UPDATE " + Tables.DATA +
383378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" +
383478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + DataColumns.MIMETYPE_ID + "=?" +
383578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "   AND " + Data.RAW_CONTACT_ID + " IN (" +
383678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            "SELECT " + RawContacts._ID +
383778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " FROM " + Tables.RAW_CONTACTS +
383878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            " WHERE " + RawContacts.CONTACT_ID + " =(" +
383978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                    "SELECT " + RawContacts.CONTACT_ID +
384078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                    " FROM " + Tables.RAW_CONTACTS +
384178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                                    " WHERE " + RawContacts._ID + "=?))");
384278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
384378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.bindLong(1, dataId);
384478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.bindLong(2, mimeTypeId);
384578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.bindLong(3, rawContactId);
384678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mSetSuperPrimaryStatement.execute();
384778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
384878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
384978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /**
385078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Inserts a record in the {@link Tables#NAME_LOOKUP} table.
385178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
385278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) {
385378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (TextUtils.isEmpty(name)) {
385478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            return;
385578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
385678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
385778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mNameLookupInsert == null) {
385878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mNameLookupInsert = getWritableDatabase().compileStatement(
385978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "("
386078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.RAW_CONTACT_ID + ","
386178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.DATA_ID + ","
386278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.NAME_TYPE + ","
386378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                            + NameLookupColumns.NORMALIZED_NAME
386478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    + ") VALUES (?,?,?,?)");
386578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
386678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.bindLong(1, rawContactId);
386778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.bindLong(2, dataId);
386878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.bindLong(3, lookupType);
386978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        bindString(mNameLookupInsert, 4, name);
387078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupInsert.executeInsert();
387178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
387278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov
387378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    /**
387478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element.
387578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov     */
387678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    public void deleteNameLookup(long dataId) {
387778fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        if (mNameLookupDelete == null) {
387878fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov            mNameLookupDelete = getWritableDatabase().compileStatement(
387978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    "DELETE FROM " + Tables.NAME_LOOKUP +
388078fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov                    " WHERE " + NameLookupColumns.DATA_ID + "=?");
388178fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        }
388278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupDelete.bindLong(1, dataId);
388378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov        mNameLookupDelete.execute();
388478fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov    }
3885189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov
3886e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public void insertNameLookupForOrganization(long rawContactId, long dataId, String company,
3887e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            String title) {
3888e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (!TextUtils.isEmpty(company)) {
3889e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            insertNameLookup(rawContactId, dataId,
3890e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov                    NameLookupType.ORGANIZATION, NameNormalizer.normalize(company));
3891e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3892e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (!TextUtils.isEmpty(title)) {
3893e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            insertNameLookup(rawContactId, dataId,
3894e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov                    NameLookupType.ORGANIZATION, NameNormalizer.normalize(title));
3895e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3896e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
3897e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3898e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public String insertNameLookupForEmail(long rawContactId, long dataId, String email) {
3899e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (TextUtils.isEmpty(email)) {
3900e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            return null;
3901e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3902e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3903e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        String address = extractHandleFromEmailAddress(email);
3904e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (address == null) {
3905e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            return null;
3906e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3907e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3908e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        insertNameLookup(rawContactId, dataId,
3909e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov                NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address));
3910e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        return address;
3911e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
3912e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3913e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    /**
3914e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov     * Normalizes the nickname and inserts it in the name lookup table.
3915e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov     */
3916e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) {
3917e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        if (TextUtils.isEmpty(nickname)) {
3918e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov            return;
3919e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        }
3920e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3921e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        insertNameLookup(rawContactId, dataId,
3922e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov                NameLookupType.NICKNAME, NameNormalizer.normalize(nickname));
3923e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
3924e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
39255df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov    public void insertNameLookupForPhoneticName(long rawContactId, long dataId, String familyName,
39265df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            String middleName, String givenName) {
39275df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        mSb.setLength(0);
39285df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (familyName != null) {
39295df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            mSb.append(familyName.trim());
39305df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
39315df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (middleName != null) {
39325df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            mSb.append(middleName.trim());
39335df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
39345df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (givenName != null) {
39355df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            mSb.append(givenName.trim());
39365df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
39375df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov
39385df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (mSb.length() > 0) {
39395df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            insertNameLookup(rawContactId, dataId, NameLookupType.NAME_COLLATION_KEY,
39405df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov                    NameNormalizer.normalize(mSb.toString()));
39415df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
39425df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov
39435df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        if (givenName != null) {
39445df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            // We want the phonetic given name to be used for search, but not for aggregation,
39455df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            // which is why we are using NAME_SHORTHAND rather than NAME_COLLATION_KEY
39465df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov            insertNameLookup(rawContactId, dataId, NameLookupType.NAME_SHORTHAND,
39475df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov                    NameNormalizer.normalize(givenName.trim()));
39485df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov        }
39495df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov    }
39505df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov
3951189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov    /**
3952189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov     * Performs a query and returns true if any Data item of the raw contact with the given
3953189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov     * id and mimetype is marked as super-primary
3954189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov     */
3955189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov    public boolean rawContactHasSuperPrimary(long rawContactId, long mimeTypeId) {
3956189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        final Cursor existsCursor = getReadableDatabase().rawQuery(
3957189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                "SELECT EXISTS(SELECT 1 FROM " + Tables.DATA +
3958189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                " WHERE " + Data.RAW_CONTACT_ID + "=?" +
3959189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                " AND " + DataColumns.MIMETYPE_ID + "=?" +
3960189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                " AND " + Data.IS_SUPER_PRIMARY + "<>0)",
3961189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov                new String[] { String.valueOf(rawContactId), String.valueOf(mimeTypeId) });
3962189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        try {
3963189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov            if (!existsCursor.moveToFirst()) throw new IllegalStateException();
3964189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov            return existsCursor.getInt(0) != 0;
3965189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        } finally {
3966189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov            existsCursor.close();
3967189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov        }
3968189273b8a9ae75d88690febfbed2d635138799ecDmitri Plotnikov    }
3969e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov
3970e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    public String getCurrentCountryIso() {
3971e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov        return mCountryMonitor.getCountryIso();
3972e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov    }
3973b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey}
3974