ContactsDatabaseHelper.java revision 7a4550f2afb24b2112b6c937f416c6f46ece35f4
1b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey/*
2b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Copyright (C) 2009 The Android Open Source Project
3b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
4b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * you may not use this file except in compliance with the License.
6b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * You may obtain a copy of the License at
7b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
8b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey *
10b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Unless required by applicable law or agreed to in writing, software
11b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * See the License for the specific language governing permissions and
14b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * limitations under the License
15b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey */
16b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarpackage com.android.providers.contacts;
18b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport com.android.internal.content.SyncStateContentProviderHelper;
2067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
21619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.ContentValues;
22b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.content.Context;
23619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.ApplicationInfo;
24619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.PackageManager;
25619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
26619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.database.Cursor;
27b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.DatabaseUtils;
28b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteDatabase;
29b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteDoneException;
30b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikovimport android.database.sqlite.SQLiteException;
31b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteOpenHelper;
32bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikovimport android.database.sqlite.SQLiteQueryBuilder;
33b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteStatement;
34b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.provider.BaseColumns;
35e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.provider.CallLog.Calls;
36b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions;
37d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.Contacts;
38de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.Data;
39ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.Groups;
401f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkeyimport android.provider.ContactsContract.Presence;
41d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts;
421f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email;
43ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership;
441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Im;
45bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone;
4667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.SocialContract.Activities;
47bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikovimport android.telephony.PhoneNumberUtils;
48b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.util.Log;
49b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
50b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport java.util.HashMap;
51b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
52b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey/**
53b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Database open helper for contacts and social activity data. Designed as a
547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * singleton to make sure that all {@link android.content.ContentProvider} users get the same
55b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * reference. Provides handy methods for maintaining package and mime-type
56b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * lookup tables.
57b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey */
58b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey/* package */ class OpenHelper extends SQLiteOpenHelper {
59b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private static final String TAG = "OpenHelper";
60b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
617a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana    private static final int DATABASE_VERSION = 61;
62b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private static final String DATABASE_NAME = "contacts2.db";
631f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    private static final String DATABASE_PRESENCE = "presence_db";
64b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
65d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov    public interface Delegate {
66d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov        void createDatabase(SQLiteDatabase db);
67d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov    }
68d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov
69b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface Tables {
707e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana        public static final String ACCOUNTS = "accounts";
71d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONTACTS = "contacts";
725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACTS = "raw_contacts";
73ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String PACKAGES = "packages";
74ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String MIMETYPES = "mimetypes";
75b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PHONE_LOOKUP = "phone_lookup";
76a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NAME_LOOKUP = "name_lookup";
77b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        public static final String AGGREGATION_EXCEPTIONS = "agg_exceptions";
78b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA = "data";
79ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String GROUPS = "groups";
801f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        public static final String PRESENCE = "presence";
81b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String NICKNAME_LOOKUP = "nickname_lookup";
82e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        public static final String CALLS = "calls";
83226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONTACT_ENTITIES = "contact_entities_view";
84b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
85d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE = "contacts "
86d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + "LEFT OUTER JOIN raw_contacts ON (contacts._id = raw_contacts.contact_id) "
875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "LEFT OUTER JOIN presence ON (raw_contacts._id = presence.raw_contact_id) "
88619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey                + "LEFT OUTER JOIN data ON (primary_phone_id = data._id)";
8900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar
90ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String DATA_JOIN_MIMETYPES = "data "
91ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id = mimetypes._id)";
92b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String DATA_JOIN_MIMETYPE_RAW_CONTACTS = "data "
94c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
95c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id)";
96bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String DATA_JOIN_RAW_CONTACTS_GROUPS = "data "
985ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "LEFT OUTER JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id)"
99ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN groups ON (groups._id = data." + GroupMembership.GROUP_ROW_ID
100ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + ")";
101ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
1025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS = "data "
10367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                + "LEFT OUTER JOIN packages ON (data.package_id = packages._id) "
10467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
1055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "LEFT OUTER JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id)";
10667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
107d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS = "data "
10867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                + "LEFT OUTER JOIN packages ON (data.package_id = packages._id) "
109ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
1105ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "LEFT OUTER JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) "
111d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
1127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana
1132815f58f72f109790585931f601a63ddc02536a5Evan Millar        public static final String RAW_CONTACTS_JOIN_CONTACTS = "raw_contacts "
1142815f58f72f109790585931f601a63ddc02536a5Evan Millar                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
1152815f58f72f109790585931f601a63ddc02536a5Evan Millar
116d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS = "data "
117ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
1185ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "LEFT OUTER JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) "
119d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
120ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
121c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        public static final String DATA_INNER_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS = "data "
122c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
123c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) "
124c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
125c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
126d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS_GROUPS =
1275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                "data "
12867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                + "LEFT OUTER JOIN packages ON (data.package_id = packages._id) "
1299261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
1309261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "LEFT OUTER JOIN groups "
1319261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "  ON (mimetypes.mimetype='" + GroupMembership.CONTENT_ITEM_TYPE + "' "
1329261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "      AND groups._id = data." + GroupMembership.GROUP_ROW_ID + ") "
1335ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "LEFT OUTER JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) "
134d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
1359261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana
1365ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_GROUPS = "data "
13767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                + "LEFT OUTER JOIN packages ON (data.package_id = packages._id) "
138ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id = mimetypes._id) "
1395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "LEFT OUTER JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) "
1409261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "LEFT OUTER JOIN groups "
1419261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "  ON (mimetypes.mimetype='" + GroupMembership.CONTENT_ITEM_TYPE + "' "
1429261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "      AND groups._id = data." + GroupMembership.GROUP_ROW_ID + ") ";
143ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
144ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String GROUPS_JOIN_PACKAGES = "groups "
145ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN packages ON (groups.package_id = packages._id)";
146ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
147d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String GROUPS_JOIN_PACKAGES_DATA_RAW_CONTACTS_CONTACTS = "groups "
148ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN packages ON (groups.package_id = packages._id) "
1499261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "LEFT OUTER JOIN data "
1509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "  ON (groups._id = data." + GroupMembership.GROUP_ROW_ID + ") "
1515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "LEFT OUTER JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) "
152d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
153b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
154b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String ACTIVITIES = "activities";
155b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
156ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String ACTIVITIES_JOIN_MIMETYPES = "activities "
157ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (activities.mimetype_id = mimetypes._id)";
158b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
159d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String ACTIVITIES_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS =
1605ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                "activities "
16167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                + "LEFT OUTER JOIN packages ON (activities.package_id = packages._id) "
162ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "LEFT OUTER JOIN mimetypes ON (activities.mimetype_id = mimetypes._id) "
1635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "LEFT OUTER JOIN raw_contacts ON (activities.author_contact_id = " +
1645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                		"raw_contacts._id) "
165d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + "LEFT OUTER JOIN contacts ON (raw_contacts.contact_id = contacts._id)";
1667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana
1675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String NAME_LOOKUP_JOIN_RAW_CONTACTS = "name_lookup "
1685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "INNER JOIN raw_contacts ON (name_lookup.raw_contact_id = raw_contacts._id)";
169b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
1705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String AGGREGATION_EXCEPTIONS_JOIN_RAW_CONTACTS = "agg_exceptions "
1715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "INNER JOIN raw_contacts raw_contacts1 "
1725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "ON (agg_exceptions.raw_contact_id1 = raw_contacts1._id) ";
173127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov
1745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String AGGREGATION_EXCEPTIONS_JOIN_RAW_CONTACTS_TWICE =
1755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                "agg_exceptions "
1765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "INNER JOIN raw_contacts raw_contacts1 "
1775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "ON (agg_exceptions.raw_contact_id1 = raw_contacts1._id) "
1785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "INNER JOIN raw_contacts raw_contacts2 "
1795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "ON (agg_exceptions.raw_contact_id2 = raw_contacts2._id) ";
180b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
181b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
1821f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    public interface Clauses {
183ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String WHERE_IM_MATCHES = MimetypesColumns.MIMETYPE + "=" + Im.MIMETYPE
1841f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey                + " AND " + Im.PROTOCOL + "=? AND " + Im.DATA + "=?";
1851f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
186ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String WHERE_EMAIL_MATCHES = MimetypesColumns.MIMETYPE + "="
1871f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey                + Email.MIMETYPE + " AND " + Email.DATA + "=?";
188ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
189ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String MIMETYPE_IS_GROUP_MEMBERSHIP = MimetypesColumns.CONCRETE_MIMETYPE
190ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + "='" + GroupMembership.CONTENT_ITEM_TYPE + "'";
191ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
192ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String BELONGS_TO_GROUP = DataColumns.CONCRETE_GROUP_ID + "="
193ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + GroupsColumns.CONCRETE_ID;
194ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
195ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String HAS_PRIMARY_PHONE = "("
196d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + ContactsColumns.OPTIMAL_PRIMARY_PHONE_ID + " IS NOT NULL OR "
197d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + ContactsColumns.FALLBACK_PRIMARY_PHONE_ID + " IS NOT NULL)";
198ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
199ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // TODO: add in check against package_visible
200ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String IN_VISIBLE_GROUP = "SELECT MIN(COUNT(" + DataColumns.CONCRETE_ID
2015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "),1) FROM " + Tables.DATA_JOIN_RAW_CONTACTS_GROUPS + " WHERE "
202d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + DataColumns.MIMETYPE_ID + "=? AND " + RawContacts.CONTACT_ID + "="
203d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + ContactsColumns.CONCRETE_ID + " AND " + Groups.GROUP_VISIBLE + "=1";
2049261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana
2059261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana        public static final String GROUP_HAS_ACCOUNT_AND_SOURCE_ID =
2069261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                Groups.SOURCE_ID + "=? AND "
2079261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                        + Groups.ACCOUNT_NAME + "=? AND "
2089261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                        + Groups.ACCOUNT_TYPE + "=?";
2091f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    }
2101f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
211d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    public interface ContactsColumns {
212619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        public static final String OPTIMAL_PRIMARY_PHONE_ID = "optimal_phone_id";
2135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String OPTIMAL_PRIMARY_PHONE_IS_RESTRICTED =
2145ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                "optimal_phone_is_restricted";
215619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        public static final String FALLBACK_PRIMARY_PHONE_ID = "fallback_phone_id";
216619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
217619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        public static final String OPTIMAL_PRIMARY_EMAIL_ID = "optimal_email_id";
2185ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String OPTIMAL_PRIMARY_EMAIL_IS_RESTRICTED =
2195ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                "optimal_email_is_restricted";
220619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        public static final String FALLBACK_PRIMARY_EMAIL_ID = "fallback_email_id";
221619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
22267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String SINGLE_IS_RESTRICTED = "single_is_restricted";
223ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
224d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_ID = Tables.CONTACTS + "." + BaseColumns._ID;
225d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_DISPLAY_NAME = Tables.CONTACTS + "."
226d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.DISPLAY_NAME;
22767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
228d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_TIMES_CONTACTED = Tables.CONTACTS + "."
229d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.TIMES_CONTACTED;
230d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_LAST_TIME_CONTACTED = Tables.CONTACTS + "."
231d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.LAST_TIME_CONTACTED;
232d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_STARRED = Tables.CONTACTS + "." + Contacts.STARRED;
233d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_CUSTOM_RINGTONE = Tables.CONTACTS + "."
234d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.CUSTOM_RINGTONE;
235d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_SEND_TO_VOICEMAIL = Tables.CONTACTS + "."
236d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.SEND_TO_VOICEMAIL;
237619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
238619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
2396cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov    public interface RawContactsColumns {
24033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_ID =
2415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + BaseColumns._ID;
2429261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana        public static final String CONCRETE_ACCOUNT_NAME =
2435ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.ACCOUNT_NAME;
2449261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana        public static final String CONCRETE_ACCOUNT_TYPE =
2455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.ACCOUNT_TYPE;
24633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_SOURCE_ID =
2475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.SOURCE_ID;
24833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_VERSION =
2495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.VERSION;
25033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_DIRTY =
2515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.DIRTY;
25233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov        public static final String CONCRETE_DELETED =
2535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Tables.RAW_CONTACTS + "." + RawContacts.DELETED;
2543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov        public static final String DISPLAY_NAME = "display_name";
2557a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC1 =
2567a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC1;
2577a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC2 =
2587a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC2;
2597a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC3 =
2607a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC3;
2617a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana        public static final String CONCRETE_SYNC4 =
2627a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                Tables.RAW_CONTACTS + "." + RawContacts.SYNC4;
263619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
264619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
265619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    public interface DataColumns {
26667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String PACKAGE_ID = "package_id";
267b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE_ID = "mimetype_id";
268ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
269ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.DATA + "." + BaseColumns._ID;
270226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_MIMETYPE_ID = Tables.DATA + "." + MIMETYPE_ID;
271d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        public static final String CONCRETE_RAW_CONTACT_ID = Tables.DATA + "."
272d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Data.RAW_CONTACT_ID;
273ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_GROUP_ID = Tables.DATA + "."
274ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + GroupMembership.GROUP_ROW_ID;
275e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov
276e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA1 = Tables.DATA + "." + Data.DATA1;
277e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA2 = Tables.DATA + "." + Data.DATA2;
278e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA3 = Tables.DATA + "." + Data.DATA3;
279e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA4 = Tables.DATA + "." + Data.DATA4;
280e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA5 = Tables.DATA + "." + Data.DATA5;
281e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA6 = Tables.DATA + "." + Data.DATA6;
282e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA7 = Tables.DATA + "." + Data.DATA7;
283e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA8 = Tables.DATA + "." + Data.DATA8;
284e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA9 = Tables.DATA + "." + Data.DATA9;
285e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_DATA10 = Tables.DATA + "." + Data.DATA10;
2860f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA11 = Tables.DATA + "." + Data.DATA11;
2870f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA12 = Tables.DATA + "." + Data.DATA12;
2880f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA13 = Tables.DATA + "." + Data.DATA13;
2890f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA14 = Tables.DATA + "." + Data.DATA14;
2900f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String CONCRETE_DATA15 = Tables.DATA + "." + Data.DATA15;
291e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_IS_PRIMARY = Tables.DATA + "." + Data.IS_PRIMARY;
292226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_PACKAGE_ID = Tables.DATA + "." + PACKAGE_ID;
293e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov    }
294e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov
2950f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    // Used only for legacy API support
2960f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    public interface ExtensionsColumns {
2970f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String NAME = Data.DATA1;
2980f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String VALUE = Data.DATA2;
2990f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    }
3000f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov
3010f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    public interface GroupMembershipColumns {
3025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = Data.RAW_CONTACT_ID;
3030f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov        public static final String GROUP_ROW_ID = GroupMembership.GROUP_ROW_ID;
3040f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov    }
3050f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov
306e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov    public interface PhoneColumns {
307e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String NORMALIZED_NUMBER = Data.DATA4;
308e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov        public static final String CONCRETE_NORMALIZED_NUMBER = DataColumns.CONCRETE_DATA4;
309ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
310ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
311ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface GroupsColumns {
31267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String PACKAGE_ID = "package_id";
31367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey
314ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.GROUPS + "." + BaseColumns._ID;
31567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey        public static final String CONCRETE_SOURCE_ID = Tables.GROUPS + "." + Groups.SOURCE_ID;
31667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey}
317b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
318b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface ActivitiesColumns {
319b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PACKAGE_ID = "package_id";
320b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE_ID = "mimetype_id";
321b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
322b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
323b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface PhoneLookupColumns {
324b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
325b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA_ID = "data_id";
3265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = "raw_contact_id";
327b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String NORMALIZED_NUMBER = "normalized_number";
328b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
329b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
330a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    public interface NameLookupColumns {
331a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String _ID = BaseColumns._ID;
3325ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID = "raw_contact_id";
333a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NORMALIZED_NAME = "normalized_name";
334a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final String NAME_TYPE = "name_type";
335a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
336a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
337a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov    public final static class NameLookupType {
338a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final int FULL_NAME = 0;
339a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final int FULL_NAME_CONCATENATED = 1;
340a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final int FULL_NAME_REVERSE = 2;
341a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        public static final int FULL_NAME_REVERSE_CONCATENATED = 3;
342b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final int FULL_NAME_WITH_NICKNAME = 4;
343b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final int FULL_NAME_WITH_NICKNAME_REVERSE = 5;
344b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final int GIVEN_NAME_ONLY = 6;
345b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final int GIVEN_NAME_ONLY_AS_NICKNAME = 7;
346b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final int FAMILY_NAME_ONLY = 8;
347b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final int FAMILY_NAME_ONLY_AS_NICKNAME = 9;
348b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final int NICKNAME = 10;
349a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        public static final int EMAIL_BASED_NICKNAME = 11;
350a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
351a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        // This is the highest name lookup type code plus one
352a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        public static final int TYPE_COUNT = 12;
353a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov
354a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        public static boolean isBasedOnStructuredName(int nameLookupType) {
355a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov            return nameLookupType != NameLookupType.EMAIL_BASED_NICKNAME
356a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov                    && nameLookupType != NameLookupType.NICKNAME;
357a5ad551e1753086825499f1aeb6415bb986f3588Dmitri Plotnikov        }
358a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
359a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
360ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface PackagesColumns {
361b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
362b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PACKAGE = "package";
363226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana
364226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        public static final String CONCRETE_ID = Tables.PACKAGES + "." + _ID;
365b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
366b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
367ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public interface MimetypesColumns {
368b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
369b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE = "mimetype";
370ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
371ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_ID = Tables.MIMETYPES + "." + BaseColumns._ID;
372ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        public static final String CONCRETE_MIMETYPE = Tables.MIMETYPES + "." + MIMETYPE;
373b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
374b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
375b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov    public interface AggregationExceptionColumns {
376b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        public static final String _ID = BaseColumns._ID;
3775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID1 = "raw_contact_id1";
3785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        public static final String RAW_CONTACT_ID2 = "raw_contact_id2";
379b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov    }
380b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
381b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    public interface NicknameLookupColumns {
382b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String NAME = "name";
383b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        public static final String CLUSTER = "cluster";
384b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    }
385b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
386b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private static final String[] NICKNAME_LOOKUP_COLUMNS = new String[] {
387b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        NicknameLookupColumns.CLUSTER
388b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    };
389b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
390b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private static final int COL_NICKNAME_LOOKUP_CLUSTER = 0;
391b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
392b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** In-memory cache of previously found mimetype mappings */
393bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    private final HashMap<String, Long> mMimetypeCache = new HashMap<String, Long>();
394b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** In-memory cache of previously found package name mappings */
395bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    private final HashMap<String, Long> mPackageCache = new HashMap<String, Long>();
396b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
397b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
398b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** Compiled statements for querying and inserting mappings */
399b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mMimetypeQuery;
400b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mPackageQuery;
401d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    private SQLiteStatement mContactIdQuery;
402f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    private SQLiteStatement mAggregationModeQuery;
403d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    private SQLiteStatement mContactIdUpdate;
404b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mMimetypeInsert;
405b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mPackageInsert;
40661bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov    private SQLiteStatement mNameLookupInsert;
407b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
408b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mDataMimetypeQuery;
409b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mActivitiesMimetypeQuery;
410b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
411b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private final Context mContext;
41235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    private final SyncStateContentProviderHelper mSyncState;
413b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private HashMap<String, String[]> mNicknameClusterCache;
414b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
415d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    /** Compiled statements for updating {@link Contacts#IN_VISIBLE_GROUP}. */
416ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    private SQLiteStatement mVisibleAllUpdate;
417ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    private SQLiteStatement mVisibleSpecificUpdate;
418ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
419d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov    private Delegate mDelegate;
420d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov
421b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private static OpenHelper sSingleton = null;
422b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
423b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public static synchronized OpenHelper getInstance(Context context) {
424b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (sSingleton == null) {
425b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            sSingleton = new OpenHelper(context);
426b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
427b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return sSingleton;
428b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
429b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
4301f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey    /**
43131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov     * Private constructor, callers except unit tests should obtain an instance through
43235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana     * {@link #getInstance(android.content.Context)} instead.
4331f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey     */
43431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov    /* package */ OpenHelper(Context context) {
435b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        super(context, DATABASE_NAME, null, DATABASE_VERSION);
436b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        Log.i(TAG, "Creating OpenHelper");
437619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
438b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        mContext = context;
43928b3769e3fcecae56c3fc70cbcb0f95282b9640eFred Quintana        mSyncState = new SyncStateContentProviderHelper();
440b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
441b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
442d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov    public Delegate getDelegate() {
443d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov        return mDelegate;
444d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov    }
445d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov
446d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov    public void setDelegate(Delegate delegate) {
447d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov        mDelegate = delegate;
448d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov    }
449d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov
450b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
451b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onOpen(SQLiteDatabase db) {
45235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        mSyncState.onDatabaseOpened(db);
45335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
454b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Create compiled statements for package and mimetype lookups
455ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mMimetypeQuery = db.compileStatement("SELECT " + MimetypesColumns._ID + " FROM "
456ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + Tables.MIMETYPES + " WHERE " + MimetypesColumns.MIMETYPE + "=?");
457ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mPackageQuery = db.compileStatement("SELECT " + PackagesColumns._ID + " FROM "
458ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + Tables.PACKAGES + " WHERE " + PackagesColumns.PACKAGE + "=?");
459d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        mContactIdQuery = db.compileStatement("SELECT " + RawContacts.CONTACT_ID + " FROM "
4605ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?");
461d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        mContactIdUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET "
462d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + RawContacts.CONTACT_ID + "=?" + " WHERE " + RawContacts._ID + "=?");
4636cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov        mAggregationModeQuery = db.compileStatement("SELECT " + RawContacts.AGGREGATION_MODE
4645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?");
465ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mMimetypeInsert = db.compileStatement("INSERT INTO " + Tables.MIMETYPES + "("
466ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + MimetypesColumns.MIMETYPE + ") VALUES (?)");
467ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mPackageInsert = db.compileStatement("INSERT INTO " + Tables.PACKAGES + "("
468ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + PackagesColumns.PACKAGE + ") VALUES (?)");
469ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
470ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mDataMimetypeQuery = db.compileStatement("SELECT " + MimetypesColumns.MIMETYPE + " FROM "
471ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + Tables.DATA_JOIN_MIMETYPES + " WHERE " + Tables.DATA + "." + Data._ID + "=?");
472ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mActivitiesMimetypeQuery = db.compileStatement("SELECT " + MimetypesColumns.MIMETYPE
473ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                + " FROM " + Tables.ACTIVITIES_JOIN_MIMETYPES + " WHERE " + Tables.ACTIVITIES + "."
474b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + Activities._ID + "=?");
47561bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov        mNameLookupInsert = db.compileStatement("INSERT INTO " + Tables.NAME_LOOKUP + "("
4765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.NAME_TYPE + ","
47761bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov                + NameLookupColumns.NORMALIZED_NAME + ") VALUES (?,?,?)");
4781f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
479d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        final String visibleUpdate = "UPDATE " + Tables.CONTACTS + " SET "
480d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + Contacts.IN_VISIBLE_GROUP + "= (" + Clauses.IN_VISIBLE_GROUP + ")";
481ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
482ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mVisibleAllUpdate = db.compileStatement(visibleUpdate);
483ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mVisibleSpecificUpdate = db.compileStatement(visibleUpdate + " WHERE "
484d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                + ContactsColumns.CONCRETE_ID + "=?");
485ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
4861f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        // Make sure we have an in-memory presence table
4871f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        final String tableName = DATABASE_PRESENCE + "." + Tables.PRESENCE;
4881f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        final String indexName = DATABASE_PRESENCE + ".presenceIndex";
4891f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
4901f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        db.execSQL("ATTACH DATABASE ':memory:' AS " + DATABASE_PRESENCE + ";");
4911f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        db.execSQL("CREATE TABLE IF NOT EXISTS " + tableName + " ("+
492c62855331805c2744a097ef6ea625652197bfb87Dmitri Plotnikov                Presence._ID + " INTEGER PRIMARY KEY," +
4935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Presence.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
4941f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey                Presence.DATA_ID + " INTEGER REFERENCES data(_id)," +
4951f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey                Presence.IM_PROTOCOL + " TEXT," +
4961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey                Presence.IM_HANDLE + " TEXT," +
4971f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey                Presence.IM_ACCOUNT + " TEXT," +
4981f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey                Presence.PRESENCE_STATUS + " INTEGER," +
4991f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey                Presence.PRESENCE_CUSTOM_STATUS + " TEXT," +
500c62855331805c2744a097ef6ea625652197bfb87Dmitri Plotnikov                "UNIQUE(" + Presence.IM_PROTOCOL + ", " + Presence.IM_HANDLE + ", "
501c62855331805c2744a097ef6ea625652197bfb87Dmitri Plotnikov                        + Presence.IM_ACCOUNT + ")" +
5021f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey        ");");
5031f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey
504fb241add950ad1314dff339805cb9eb2d6136f96Jeff Sharkey        db.execSQL("CREATE INDEX IF NOT EXISTS " + indexName + " ON " + Tables.PRESENCE + " ("
5055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + Presence.RAW_CONTACT_ID + ");");
506b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
507b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
508b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
509b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onCreate(SQLiteDatabase db) {
510b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        Log.i(TAG, "Bootstrapping database");
511b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
51235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        mSyncState.createDatabase(db);
51335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
514b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // One row per group of contacts corresponding to the same person
515d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.CONTACTS + " (" +
516b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
517d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.DISPLAY_NAME + " TEXT," +
518d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.PHOTO_ID + " INTEGER REFERENCES data(_id)," +
519d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.CUSTOM_RINGTONE + " TEXT," +
520d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," +
521d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," +
522d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.LAST_TIME_CONTACTED + " INTEGER," +
523d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.STARRED + " INTEGER NOT NULL DEFAULT 0," +
524d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                Contacts.IN_VISIBLE_GROUP + " INTEGER NOT NULL DEFAULT 1," +
525d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                ContactsColumns.OPTIMAL_PRIMARY_PHONE_ID + " INTEGER REFERENCES data(_id)," +
526d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                ContactsColumns.OPTIMAL_PRIMARY_PHONE_IS_RESTRICTED + " INTEGER DEFAULT 0," +
527d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                ContactsColumns.FALLBACK_PRIMARY_PHONE_ID + " INTEGER REFERENCES data(_id)," +
528d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                ContactsColumns.OPTIMAL_PRIMARY_EMAIL_ID + " INTEGER REFERENCES data(_id)," +
529d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                ContactsColumns.OPTIMAL_PRIMARY_EMAIL_IS_RESTRICTED + " INTEGER DEFAULT 0," +
530d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                ContactsColumns.FALLBACK_PRIMARY_EMAIL_ID + " INTEGER REFERENCES data(_id)," +
531d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                ContactsColumns.SINGLE_IS_RESTRICTED + " INTEGER REFERENCES package(_id)" +
532b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
533b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
534b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Contacts table
5355ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.RAW_CONTACTS + " (" +
5366cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
5376cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.IS_RESTRICTED + " INTEGER DEFAULT 0," +
5386cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.ACCOUNT_NAME + " STRING DEFAULT NULL, " +
5396cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.ACCOUNT_TYPE + " STRING DEFAULT NULL, " +
5406cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.SOURCE_ID + " TEXT," +
5416cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.VERSION + " INTEGER NOT NULL DEFAULT 1," +
5426cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.DIRTY + " INTEGER NOT NULL DEFAULT 1," +
54333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov                RawContacts.DELETED + " INTEGER NOT NULL DEFAULT 0," +
544d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov                RawContacts.CONTACT_ID + " INTEGER," +
5456cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.AGGREGATION_MODE + " INTEGER NOT NULL DEFAULT " +
5466cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                        RawContacts.AGGREGATION_MODE_DEFAULT + "," +
5476cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.CUSTOM_RINGTONE + " TEXT," +
5486cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.SEND_TO_VOICEMAIL + " INTEGER NOT NULL DEFAULT 0," +
5496cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.TIMES_CONTACTED + " INTEGER NOT NULL DEFAULT 0," +
5506cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov                RawContacts.LAST_TIME_CONTACTED + " INTEGER," +
55133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov                RawContacts.STARRED + " INTEGER NOT NULL DEFAULT 0," +
5523cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContactsColumns.DISPLAY_NAME + " TEXT," +
5533cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC1 + " TEXT, " +
5543cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC2 + " TEXT, " +
5553cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC3 + " TEXT, " +
5563cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                RawContacts.SYNC4 + " TEXT " +
557b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
558b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
559b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Package name mapping table
560ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PACKAGES + " (" +
561ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                PackagesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
562ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                PackagesColumns.PACKAGE + " TEXT NOT NULL" +
563b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
564b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
565ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // Mimetype mapping table
566ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.MIMETYPES + " (" +
567ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                MimetypesColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
568ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                MimetypesColumns.MIMETYPE + " TEXT NOT NULL" +
569b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
570b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
571b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Public generic data table
572b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.DATA + " (" +
573b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
57467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                DataColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
575b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                DataColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
5765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Data.RAW_CONTACT_ID + " INTEGER NOT NULL," +
577f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.IS_PRIMARY + " INTEGER NOT NULL DEFAULT 0," +
578f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.IS_SUPER_PRIMARY + " INTEGER NOT NULL DEFAULT 0," +
579f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA_VERSION + " INTEGER NOT NULL DEFAULT 0," +
580f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA1 + " TEXT," +
581f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA2 + " TEXT," +
582f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA3 + " TEXT," +
583f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA4 + " TEXT," +
584f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA5 + " TEXT," +
585f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA6 + " TEXT," +
586f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA7 + " TEXT," +
587f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA8 + " TEXT," +
588f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                Data.DATA9 + " TEXT," +
58967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA10 + " TEXT," +
59067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA11 + " TEXT," +
59167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA12 + " TEXT," +
59267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA13 + " TEXT," +
59367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Data.DATA14 + " TEXT," +
5943cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.DATA15 + " TEXT," +
5953cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC1 + " TEXT, " +
5963cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC2 + " TEXT, " +
5973cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC3 + " TEXT, " +
5983cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Data.SYNC4 + " TEXT " +
599b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
600b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
601f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana        /**
60261d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov         * Automatically delete Data rows when a raw contact is deleted.
603f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana         */
6045ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_deleted "
6055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "   BEFORE DELETE ON " + Tables.RAW_CONTACTS
606f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                + " BEGIN "
607f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                + "   DELETE FROM " + Tables.DATA
6085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "     WHERE " + Data.RAW_CONTACT_ID + "=OLD." + RawContacts._ID + ";"
609f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                + "   DELETE FROM " + Tables.PHONE_LOOKUP
6105ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "     WHERE " + PhoneLookupColumns.RAW_CONTACT_ID + "=OLD." + RawContacts._ID + ";"
611f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                + " END");
612f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana
61361d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov        /**
61461d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov         * Triggers that set {@link RawContacts#DIRTY} and update {@link RawContacts#VERSION}
61561d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov         * when the contact is marked for deletion or any time a data row is inserted, updated
61661d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov         * or deleted.
61761d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov         */
61861d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov        db.execSQL("CREATE TRIGGER " + Tables.RAW_CONTACTS + "_marked_deleted "
61961d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                + "   BEFORE UPDATE ON " + Tables.RAW_CONTACTS
62061d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                + " BEGIN "
62161d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
62261d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                + "     SET "
62361d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                +         RawContacts.VERSION + "=OLD." + RawContacts.VERSION + "+1, "
62461d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                +         RawContacts.DIRTY + "=1"
62561d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + RawContacts._ID
62661d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                + "       AND NEW." + RawContacts.DELETED + "!= OLD." + RawContacts.DELETED + ";"
62761d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                + " END");
62861d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov
629f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_updated AFTER UPDATE ON " + Tables.DATA
630f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                + " BEGIN "
631f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                + "   UPDATE " + Tables.DATA
632f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                + "     SET " + Data.DATA_VERSION + "=OLD." + Data.DATA_VERSION + "+1 "
633f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                + "     WHERE " + Data._ID + "=OLD." + Data._ID + ";"
6345ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
63561d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                + "     SET " + RawContacts.DIRTY + "=1, "
63661d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                + "         " +	RawContacts.VERSION + "=" + RawContacts.VERSION + "+1 "
6375ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + Data.RAW_CONTACT_ID + ";"
638f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                + " END");
639f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana
6401fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_inserted BEFORE INSERT ON " + Tables.DATA
6411fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana                + " BEGIN "
64217392c6de42c9617117eb16ee2d937064a447a2cDmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
64361d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                + "     SET " + RawContacts.DIRTY + "=1, "
64461d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                + "         " + RawContacts.VERSION + "=" + RawContacts.VERSION + "+1 "
64517392c6de42c9617117eb16ee2d937064a447a2cDmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=NEW." + Data.RAW_CONTACT_ID + ";"
6461fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana                + " END");
6471fd9b53d9e5d8ea87b69a51fb084c6f0d9f7c93eFred Quintana
648f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana        db.execSQL("CREATE TRIGGER " + Tables.DATA + "_deleted BEFORE DELETE ON " + Tables.DATA
649f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                + " BEGIN "
6505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "   UPDATE " + Tables.RAW_CONTACTS
65161d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                + "     SET " + RawContacts.DIRTY + "=1,"
65261d61cb4d13a33c5581765fb4c0f1b3c0b2cdf4cDmitri Plotnikov                + "         " + RawContacts.VERSION + "=" + RawContacts.VERSION + "+1 "
6535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                + "     WHERE " + RawContacts._ID + "=OLD." + Data.RAW_CONTACT_ID + ";"
654f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                + "   DELETE FROM " + Tables.PHONE_LOOKUP
655f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                + "     WHERE " + PhoneLookupColumns.DATA_ID + "=OLD." + Data._ID + ";"
656f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana                + " END");
657f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana
658b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Private phone numbers table used for lookup
659b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" +
660b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns._ID + " INTEGER PRIMARY KEY," +
661b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.DATA_ID + " INTEGER REFERENCES data(_id) NOT NULL," +
6625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID
6635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
664b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL" +
665b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
666b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
667b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" +
668b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.NORMALIZED_NUMBER + " ASC, " +
6695ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                PhoneLookupColumns.RAW_CONTACT_ID + ", " +
670b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.DATA_ID +
671b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
672b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
673a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        // Private name/nickname table used for lookup
674a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.NAME_LOOKUP + " (" +
675a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov                NameLookupColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
6765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID
6775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," +
678619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey                NameLookupColumns.NORMALIZED_NAME + " TEXT," +
679a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov                NameLookupColumns.NAME_TYPE + " INTEGER" +
680a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        ");");
681a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
682a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("CREATE INDEX name_lookup_index ON " + Tables.NAME_LOOKUP + " (" +
683a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov                NameLookupColumns.NORMALIZED_NAME + " ASC, " +
684a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov                NameLookupColumns.NAME_TYPE + " ASC, " +
6855ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                NameLookupColumns.RAW_CONTACT_ID +
686a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        ");");
687a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov
688b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.NICKNAME_LOOKUP + " (" +
689b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + " TEXT," +
690b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.CLUSTER + " TEXT" +
691b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        ");");
692b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
693b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX nickname_lookup_index ON " + Tables.NICKNAME_LOOKUP + " (" +
694b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + ", " +
695b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.CLUSTER +
696b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        ");");
697b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
698ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        // Groups table
699ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.GROUPS + " (" +
700ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
70167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                GroupsColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
702035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana                Groups.ACCOUNT_NAME + " STRING DEFAULT NULL, " +
703035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana                Groups.ACCOUNT_TYPE + " STRING DEFAULT NULL, " +
704ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups.SOURCE_ID + " TEXT," +
7059261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                Groups.VERSION + " INTEGER NOT NULL DEFAULT 1," +
7069261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                Groups.DIRTY + " INTEGER NOT NULL DEFAULT 1," +
707ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey                Groups.TITLE + " TEXT," +
70867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                Groups.TITLE_RES + " INTEGER," +
7090f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov                Groups.NOTES + " TEXT," +
7100f8f3b3e4a6ad18c5868d0215cc137845a2ddc74Dmitri Plotnikov                Groups.SYSTEM_ID + " TEXT," +
7113cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.GROUP_VISIBLE + " INTEGER," +
7123cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC1 + " TEXT, " +
7133cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC2 + " TEXT, " +
7143cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC3 + " TEXT, " +
7153cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov                Groups.SYNC4 + " TEXT " +
716ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        ");");
717ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
7189261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana        db.execSQL("CREATE TRIGGER " + Tables.GROUPS + "_updated1 "
7199261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "   BEFORE UPDATE ON " + Tables.GROUPS
7209261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + " BEGIN "
7219261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "   UPDATE " + Tables.GROUPS
7229261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "     SET "
7239261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                +         Groups.VERSION + "=OLD." + Groups.VERSION + "+1, "
7249261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                +         Groups.DIRTY + "=1"
7259261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + "     WHERE " + Groups._ID + "=OLD." + Groups._ID + ";"
7269261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana                + " END");
7279261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana
728b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.AGGREGATION_EXCEPTIONS + " (" +
729b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                AggregationExceptionColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
730b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                AggregationExceptions.TYPE + " INTEGER NOT NULL, " +
7315ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                AggregationExceptionColumns.RAW_CONTACT_ID1
7325ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id), " +
7335ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                AggregationExceptionColumns.RAW_CONTACT_ID2
7345ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                        + " INTEGER REFERENCES raw_contacts(_id)" +
735b0160a0bcf6d59eaa43fd501e124b95f873e0157Marc Blank        ");");
736b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
737b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index1 ON " +
738b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                Tables.AGGREGATION_EXCEPTIONS + " (" +
7395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                AggregationExceptionColumns.RAW_CONTACT_ID1 + ", " +
7405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                AggregationExceptionColumns.RAW_CONTACT_ID2 +
741b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        ");");
742b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
743b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS aggregation_exception_index2 ON " +
744b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov                Tables.AGGREGATION_EXCEPTIONS + " (" +
7455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                AggregationExceptionColumns.RAW_CONTACT_ID2 + ", " +
7465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                AggregationExceptionColumns.RAW_CONTACT_ID1 +
747b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        ");");
748b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
749e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        // The table for recent calls is here so we can do table joins
750e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        // on people, phones, and calls all in one place.
751e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        db.execSQL("CREATE TABLE " + Tables.CALLS + " (" +
752e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
753e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.NUMBER + " TEXT," +
754e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.DATE + " INTEGER," +
755e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.DURATION + " INTEGER," +
756e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.TYPE + " INTEGER," +
757e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.NEW + " INTEGER," +
758e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NAME + " TEXT," +
759e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NUMBER_TYPE + " INTEGER," +
760e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov                Calls.CACHED_NUMBER_LABEL + " TEXT" +
761e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov        ");");
762e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov
763b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Activities table
764b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.ACTIVITIES + " (" +
765b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
76667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey                ActivitiesColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id)," +
767b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                ActivitiesColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
768b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.RAW_ID + " TEXT," +
769499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.IN_REPLY_TO + " TEXT," +
7705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Activities.AUTHOR_CONTACT_ID +  " INTEGER REFERENCES raw_contacts(_id)," +
7715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov                Activities.TARGET_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id)," +
772b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.PUBLISHED + " INTEGER NOT NULL," +
773499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.THREAD_PUBLISHED + " INTEGER NOT NULL," +
774b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.TITLE + " TEXT NOT NULL," +
775b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.SUMMARY + " TEXT," +
776adb55c2d8295d300961d86a3605c8ddc469cd4a2Dmitri Plotnikov                Activities.LINK + " TEXT, " +
777b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.THUMBNAIL + " BLOB" +
778b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
779b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
780226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana        db.execSQL("CREATE VIEW " + Tables.CONTACT_ENTITIES + " AS SELECT "
781226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AS " + RawContacts.ACCOUNT_NAME + ","
782226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AS " + RawContacts.ACCOUNT_TYPE + ","
783226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + RawContactsColumns.CONCRETE_SOURCE_ID + " AS " + RawContacts.SOURCE_ID + ","
784226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + RawContactsColumns.CONCRETE_VERSION + " AS " + RawContacts.VERSION + ","
785226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + RawContactsColumns.CONCRETE_DIRTY + " AS " + RawContacts.DIRTY + ","
786226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + PackagesColumns.PACKAGE + " AS " + Data.RES_PACKAGE + ","
787e7c19a079df0ba9be2fbba494ba6efd838658f78Fred Quintana                + RawContacts.CONTACT_ID + ", "
7887a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                + RawContactsColumns.CONCRETE_SYNC1 + " AS " + RawContacts.SYNC1 + ", "
7897a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                + RawContactsColumns.CONCRETE_SYNC2 + " AS " + RawContacts.SYNC2 + ", "
7907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                + RawContactsColumns.CONCRETE_SYNC3 + " AS " + RawContacts.SYNC3 + ", "
7917a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                + RawContactsColumns.CONCRETE_SYNC4 + " AS " + RawContacts.SYNC4 + ", "
792226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.MIMETYPE + ", "
793226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA1 + ", "
794226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA2 + ", "
795226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA3 + ", "
796226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA4 + ", "
797226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA5 + ", "
798226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA6 + ", "
799226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA7 + ", "
800226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA8 + ", "
801226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA9 + ", "
802226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA10 + ", "
803226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA11 + ", "
804226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA12 + ", "
805226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA13 + ", "
806226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA14 + ", "
807226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA15 + ", "
8087a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                + Data.SYNC1 + ", "
8097a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                + Data.SYNC2 + ", "
8107a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                + Data.SYNC3 + ", "
8117a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana                + Data.SYNC4 + ", "
812226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.RAW_CONTACT_ID + ", "
813226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.IS_PRIMARY + ", "
814226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Data.DATA_VERSION + ", "
815226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + DataColumns.CONCRETE_ID + " AS " + RawContacts._ID + ","
816226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + Tables.GROUPS + "." + Groups.SOURCE_ID + " AS " + GroupMembership.GROUP_SOURCE_ID
817226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + " FROM " + Tables.DATA
818226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + " LEFT OUTER JOIN " + Tables.PACKAGES + " ON ("
819226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                +   DataColumns.CONCRETE_PACKAGE_ID + "=" + PackagesColumns.CONCRETE_ID + ")"
820226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + " LEFT OUTER JOIN " + Tables.MIMETYPES + " ON ("
821226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                +   DataColumns.CONCRETE_MIMETYPE_ID + "=" + MimetypesColumns.CONCRETE_ID + ")"
822226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + " LEFT OUTER JOIN " + Tables.RAW_CONTACTS + " ON ("
823226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                +   DataColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID + ")"
824226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                + " LEFT OUTER JOIN " + Tables.GROUPS + " ON ("
825226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                +   MimetypesColumns.CONCRETE_MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
826226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana                +   "' AND " + GroupsColumns.CONCRETE_ID + "=" + DataColumns.CONCRETE_DATA1 + ")");
827226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana
828b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        loadNicknameLookupTable(db);
829d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov        if (mDelegate != null) {
830d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov            mDelegate.createDatabase(db);
831d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov        }
832b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
833b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
834b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
835b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
8367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana        Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion
837b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + ", data will be lost!");
838b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
8397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana        db.execSQL("DROP TABLE IF EXISTS " + Tables.ACCOUNTS + ";");
840d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS " + Tables.CONTACTS + ";");
8415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS " + Tables.RAW_CONTACTS + ";");
842ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("DROP TABLE IF EXISTS " + Tables.PACKAGES + ";");
843ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("DROP TABLE IF EXISTS " + Tables.MIMETYPES + ";");
844b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("DROP TABLE IF EXISTS " + Tables.DATA + ";");
845b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("DROP TABLE IF EXISTS " + Tables.PHONE_LOOKUP + ";");
846a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS " + Tables.NAME_LOOKUP + ";");
847b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS " + Tables.NICKNAME_LOOKUP + ";");
848ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("DROP TABLE IF EXISTS " + Tables.GROUPS + ";");
849b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("DROP TABLE IF EXISTS " + Tables.ACTIVITIES + ";");
8503d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS " + Tables.CALLS + ";");
851b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
852f1ce2d5008e490f447d6f5ff04a784c8ae066e9dJeff Sharkey        db.execSQL("DROP VIEW IF EXISTS " + Tables.CONTACT_ENTITIES + ";");
853f1ce2d5008e490f447d6f5ff04a784c8ae066e9dJeff Sharkey
854d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov        // TODO: we should not be dropping agg_exceptions and contact_options. In case that table's
855d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov        // schema changes, we should try to preserve the data, because it was entered by the user
856d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov        // and has never been synched to the server.
857d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov        db.execSQL("DROP TABLE IF EXISTS " + Tables.AGGREGATION_EXCEPTIONS + ";");
858b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov
859b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        onCreate(db);
86035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana
861f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        // TODO: eventually when this supports upgrades we should do something like the following:
86235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana//        if (!upgradeDatabase(db, oldVersion, newVersion)) {
86335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana//            mSyncState.discardSyncData(db, null /* all accounts */);
86435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana//            ContentResolver.requestSync(null /* all accounts */,
86535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana//                    mContentUri.getAuthority(), new Bundle());
86635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana//        }
867b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
868b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
869a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    /**
870a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov     * Wipes all data except mime type and package lookup tables.
871a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov     */
872a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    public void wipeData() {
873a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
8743d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov
875d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CONTACTS + ";");
8765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.RAW_CONTACTS + ";");
877a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.DATA + ";");
878a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.PHONE_LOOKUP + ";");
879a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.NAME_LOOKUP + ";");
880ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        db.execSQL("DELETE FROM " + Tables.GROUPS + ";");
881b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.AGGREGATION_EXCEPTIONS + ";");
882a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.ACTIVITIES + ";");
8833d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CALLS + ";");
884b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
885b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        // Note: we are not removing reference data from Tables.NICKNAME_LOOKUP
886b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
887a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov        db.execSQL("VACUUM;");
888a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov    }
889b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
890b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
891619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey     * Return the {@link ApplicationInfo#uid} for the given package name.
892619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey     */
893619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    public static int getUidForPackageName(PackageManager pm, String packageName) {
894619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        try {
895619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            ApplicationInfo clientInfo = pm.getApplicationInfo(packageName, 0 /* no flags */);
896619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            return clientInfo.uid;
897619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        } catch (NameNotFoundException e) {
898619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey            throw new RuntimeException(e);
899619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey        }
900619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    }
901619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
902619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    /**
903b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Perform an internal string-to-integer lookup using the compiled
904b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * {@link SQLiteStatement} provided, using the in-memory cache to speed up
905b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups. If a mapping isn't found in cache or database, it will be
906b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * created. All new, uncached answers are added to the cache automatically.
907b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *
908b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param query Compiled statement used to query for the mapping.
909b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param insert Compiled statement used to insert a new mapping when no
910b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *            existing one is found in cache or from query.
911b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param value Value to find mapping for.
912b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param cache In-memory cache of previous answers.
913b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @return An unique integer mapping for the given value.
914b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
915b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private synchronized long getCachedId(SQLiteStatement query, SQLiteStatement insert,
916b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String value, HashMap<String, Long> cache) {
917b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Try an in-memory cache lookup
918b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (cache.containsKey(value)) {
919b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return cache.get(value);
920b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
921b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
922b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        long id = -1;
923b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
924b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try searching database for mapping
925b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(query, 1, value);
926b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            id = query.simpleQueryForLong();
927b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
928b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Nothing found, so try inserting new mapping
929b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(insert, 1, value);
930b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            id = insert.executeInsert();
931b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
932b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
933b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (id != -1) {
934b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Cache and return the new answer
935b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            cache.put(value, id);
936b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return id;
937b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } else {
938b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Otherwise throw if no mapping found or created
939b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            throw new IllegalStateException("Couldn't find or create internal "
940b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                    + "lookup table entry for value " + value);
941b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
942b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
943b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
944b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
945ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Convert a package name into an integer, using {@link Tables#PACKAGES} for
946b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
947b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
948b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getPackageId(String packageName) {
949b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
950b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
951b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return getCachedId(mPackageQuery, mPackageInsert, packageName, mPackageCache);
952b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
953b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
954b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
955ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Convert a mimetype into an integer, using {@link Tables#MIMETYPES} for
956b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
957b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
958b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getMimeTypeId(String mimetype) {
959b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
960b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
961b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return getCachedId(mMimetypeQuery, mMimetypeInsert, mimetype, mMimetypeCache);
962b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
963b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
964b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
965ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     * Find the mimetype for the given {@link Data#_ID}.
966b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
967b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getDataMimeType(long dataId) {
968b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
969b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
970b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
971b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
972b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mDataMimetypeQuery, 1, dataId);
973b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mDataMimetypeQuery.simpleQueryForString();
974b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
975b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
976b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
977b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
978b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
979b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
980b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
981b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
982b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Find the mime-type for the given {@link Activities#_ID}.
983b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
984b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getActivityMimeType(long activityId) {
985b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
986b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
987b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
988b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
989b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mActivitiesMimetypeQuery, 1, activityId);
990b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mActivitiesMimetypeQuery.simpleQueryForString();
991b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
992b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
993b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
994b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
995b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
996b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
9976bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov
9986bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov    /**
999d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Update {@link Contacts#IN_VISIBLE_GROUP} for all contacts.
1000ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     */
1001ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    public void updateAllVisible() {
1002ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        final long groupMembershipMimetypeId = getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
1003ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mVisibleAllUpdate.bindLong(1, groupMembershipMimetypeId);
1004ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mVisibleAllUpdate.execute();
1005ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
1006ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
1007ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    /**
1008d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Update {@link Contacts#IN_VISIBLE_GROUP} for a specific contact.
1009ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey     */
1010d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    public void updateContactVisible(long aggId) {
1011ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        final long groupMembershipMimetypeId = getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
1012ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mVisibleSpecificUpdate.bindLong(1, groupMembershipMimetypeId);
1013ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mVisibleSpecificUpdate.bindLong(2, aggId);
1014ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        mVisibleSpecificUpdate.execute();
1015ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    }
1016ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey
1017ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey    /**
1018d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Updates the contact ID for the specified contact.
101961bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov     */
1020d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    public void setContactId(long rawContactId, long contactId) {
102161bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov        getWritableDatabase();
1022d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        DatabaseUtils.bindObjectToProgram(mContactIdUpdate, 1, contactId);
1023d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        DatabaseUtils.bindObjectToProgram(mContactIdUpdate, 2, rawContactId);
1024d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov        mContactIdUpdate.execute();
102561bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov    }
102661bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov
102761bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov    /**
1028d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov     * Returns contact ID for the given contact or zero if it is NULL.
10296bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov     */
1030d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov    public long getContactId(long rawContactId) {
10316bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        getReadableDatabase();
10326bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        try {
1033d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov            DatabaseUtils.bindObjectToProgram(mContactIdQuery, 1, rawContactId);
1034d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov            return mContactIdQuery.simpleQueryForLong();
10356bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        } catch (SQLiteDoneException e) {
10366bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov            // No valid mapping found, so return -1
10376bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov            return 0;
10386bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov        }
10396bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov    }
104061bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov
10415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov    public int getAggregationMode(long rawContactId) {
1042f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        getReadableDatabase();
1043f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        try {
10445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov            DatabaseUtils.bindObjectToProgram(mAggregationModeQuery, 1, rawContactId);
1045f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            return (int)mAggregationModeQuery.simpleQueryForLong();
1046f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        } catch (SQLiteDoneException e) {
10476cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov            // No valid row found, so return "disabled"
10486cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov            return RawContacts.AGGREGATION_MODE_DISABLED;
1049f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
1050f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
1051f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
105261bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov    /**
105361bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov     * Inserts a record in the {@link Tables#NAME_LOOKUP} table.
105461bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov     */
10555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov    public void insertNameLookup(long rawContactId, int lookupType, String name) {
105661bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov        getWritableDatabase();
10575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 1, rawContactId);
105861bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov        DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 2, lookupType);
105961bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov        DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 3, name);
106061bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov        mNameLookupInsert.executeInsert();
106161bbb2287e8102b7e03922c03809c34b7b317d1cDmitri Plotnikov    }
1062619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey
1063bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    public static void buildPhoneLookupQuery(SQLiteQueryBuilder qb, final String number) {
1064bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov        final String normalizedNumber = PhoneNumberUtils.toCallerIDMinMatch(number);
1065bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov        final StringBuilder tables = new StringBuilder();
10665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        tables.append(Tables.RAW_CONTACTS + ", (SELECT data_id FROM phone_lookup "
1067bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov                + "WHERE (phone_lookup.normalized_number GLOB '");
1068bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov        tables.append(normalizedNumber);
1069ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey        tables.append("*')) AS lookup, " + Tables.DATA_JOIN_MIMETYPES);
1070bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov        qb.setTables(tables.toString());
10715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov        qb.appendWhere("lookup.data_id=data._id AND data.raw_contact_id=raw_contacts._id AND ");
1072bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov        qb.appendWhere("PHONE_NUMBERS_EQUAL(data." + Phone.NUMBER + ", ");
1073bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov        qb.appendWhereEscapeString(number);
1074bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov        qb.appendWhere(")");
1075bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov    }
1076bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
1077bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov
1078619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey    /**
1079b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     * Loads common nickname mappings into the database.
1080b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     */
1081b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    private void loadNicknameLookupTable(SQLiteDatabase db) {
108228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar        String[] strings = mContext.getResources().getStringArray(
108328f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar                com.android.internal.R.array.common_nicknames);
1084b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        if (strings == null || strings.length == 0) {
1085b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            return;
1086b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
1087b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
1088b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        SQLiteStatement nicknameLookupInsert = db.compileStatement("INSERT INTO "
1089b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                + Tables.NICKNAME_LOOKUP + "(" + NicknameLookupColumns.NAME + ","
1090b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                + NicknameLookupColumns.CLUSTER + ") VALUES (?,?)");
1091b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
1092b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        for (int clusterId = 0; clusterId < strings.length; clusterId++) {
1093b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            String[] names = strings[clusterId].split(",");
1094b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            for (int j = 0; j < names.length; j++) {
1095b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                String name = NameNormalizer.normalize(names[j]);
1096b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                try {
1097b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                    DatabaseUtils.bindObjectToProgram(nicknameLookupInsert, 1, name);
1098b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                    DatabaseUtils.bindObjectToProgram(nicknameLookupInsert, 2,
1099b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                            String.valueOf(clusterId));
1100b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                    nicknameLookupInsert.executeInsert();
1101b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                } catch (SQLiteException e) {
1102b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
1103b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                    // Print the exception and keep going - this is not a fatal error
1104b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                    Log.e(TAG, "Cannot insert nickname: " + names[j], e);
1105b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                }
1106b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            }
1107b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
1108b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    }
1109b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
1110b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    /**
1111b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     * Returns common nickname cluster IDs for a given name. For example, it
1112b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     * will return the same value for "Robert", "Bob" and "Rob". Some names belong to multiple
1113b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     * clusters, e.g. Leo could be Leonard or Leopold.
1114b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     *
1115b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     * May return null.
1116b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     *
1117b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     * @param normalizedName A normalized first name, see {@link NameNormalizer#normalize}.
1118b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov     */
1119b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    public String[] getCommonNicknameClusters(String normalizedName) {
1120b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        if (mNicknameClusterCache == null) {
1121b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            mNicknameClusterCache = new HashMap<String, String[]>();
1122b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
1123b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
1124b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        synchronized (mNicknameClusterCache) {
1125b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            if (mNicknameClusterCache.containsKey(normalizedName)) {
1126b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                return mNicknameClusterCache.get(normalizedName);
1127b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            }
1128b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
1129b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
1130b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        String[] clusters = null;
1131b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        SQLiteDatabase db = getReadableDatabase();
1132b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
1133b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        Cursor cursor = db.query(Tables.NICKNAME_LOOKUP, NICKNAME_LOOKUP_COLUMNS,
1134b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                NicknameLookupColumns.NAME + "=?", new String[] { normalizedName },
1135b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                null, null, null);
1136b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        try {
1137b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            int count = cursor.getCount();
1138b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            if (count > 0) {
1139b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                clusters = new String[count];
1140b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                for (int i = 0; i < count; i++) {
1141b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                    cursor.moveToNext();
1142b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                    clusters[i] = cursor.getString(COL_NICKNAME_LOOKUP_CLUSTER);
1143b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov                }
1144b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            }
1145b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        } finally {
1146b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            cursor.close();
1147b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
1148b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
1149b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        synchronized (mNicknameClusterCache) {
1150b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov            mNicknameClusterCache.put(normalizedName, clusters);
1151b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        }
1152b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
1153b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov        return clusters;
1154b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov    }
1155b597adb79f1f57a24be2be09e3f45fa0f04f6f8fDmitri Plotnikov
1156f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    public static void copyStringValue(ContentValues toValues, String toKey,
1157f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            ContentValues fromValues, String fromKey) {
1158f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        if (fromValues.containsKey(fromKey)) {
1159f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            toValues.put(toKey, fromValues.getAsString(fromKey));
1160f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
1161f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
1162f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
1163f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    public static void copyLongValue(ContentValues toValues, String toKey,
1164f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            ContentValues fromValues, String fromKey) {
1165f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        if (fromValues.containsKey(fromKey)) {
1166f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            long longValue;
1167f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            Object value = fromValues.get(fromKey);
1168f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            if (value instanceof Boolean) {
1169f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                if ((Boolean)value) {
1170f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                    longValue = 1;
1171f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                } else {
1172f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                    longValue = 0;
1173f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                }
1174f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            } else {
1175f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov                longValue = ((Number) value).longValue();
1176f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            }
1177f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov            toValues.put(toKey, longValue);
1178f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov        }
1179f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov    }
1180f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov
118135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    public SyncStateContentProviderHelper getSyncState() {
118235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana        return mSyncState;
118335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana    }
1184c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
1185c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    /**
1186c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     * Delete the aggregate contact if it has no constituent raw contacts other
1187c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     * than the supplied one.
1188c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov     */
1189c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    public void removeContactIfSingleton(long rawContactId) {
1190c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        SQLiteDatabase db = getWritableDatabase();
1191c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
1192c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        // Obtain contact ID from the supplied raw contact ID
1193c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        String contactIdFromRawContactId = "(SELECT " + RawContacts.CONTACT_ID + " FROM "
1194c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=" + rawContactId + ")";
1195c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
1196c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        // Find other raw contacts in the same aggregate contact
1197c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        String otherRawContacts = "(SELECT contacts1." + RawContacts._ID + " FROM "
1198c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + Tables.RAW_CONTACTS + " contacts1 JOIN " + Tables.RAW_CONTACTS + " contacts2 ON ("
1199c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + "contacts1." + RawContacts.CONTACT_ID + "=contacts2." + RawContacts.CONTACT_ID
1200c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + ") WHERE contacts1." + RawContacts._ID + "!=" + rawContactId + ""
1201c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " AND contacts2." + RawContacts._ID + "=" + rawContactId + ")";
1202c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov
1203c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov        db.execSQL("DELETE FROM " + Tables.CONTACTS
1204c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " WHERE " + Contacts._ID + "=" + contactIdFromRawContactId
1205c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov                + " AND NOT EXISTS " + otherRawContacts + ";");
1206c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov    }
1207b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey}
1208