ContactsDatabaseHelper.java revision adb55c2d8295d300961d86a3605c8ddc469cd4a2
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
17b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeypackage com.android.providers.contacts2;
18b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
19b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport com.android.providers.contacts2.SocialContract.Activities;
20b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport com.android.providers.contacts2.ContactsContract.Aggregates;
21b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport com.android.providers.contacts2.ContactsContract.Contacts;
22b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport com.android.providers.contacts2.ContactsContract.Data;
23b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
24b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.content.Context;
25b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.DatabaseUtils;
26b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteDatabase;
27b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteDoneException;
28b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteOpenHelper;
29b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.database.sqlite.SQLiteStatement;
30b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.provider.BaseColumns;
31b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.util.Log;
32b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
33b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport java.util.HashMap;
34b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
35b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey/**
36b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * Database open helper for contacts and social activity data. Designed as a
37b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * singleton to make sure that all {@link ContentProvider} users get the same
38b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * reference. Provides handy methods for maintaining package and mime-type
39b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey * lookup tables.
40b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey */
41b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey/* package */ class OpenHelper extends SQLiteOpenHelper {
42b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private static final String TAG = "OpenHelper";
43b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
44adb55c2d8295d300961d86a3605c8ddc469cd4a2Dmitri Plotnikov    private static final int DATABASE_VERSION = 16;
45b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private static final String DATABASE_NAME = "contacts2.db";
46b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
47b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface Tables {
48b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String AGGREGATES = "aggregates";
49b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String CONTACTS = "contacts";
50b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PACKAGE = "package";
51b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE = "mimetype";
52b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PHONE_LOOKUP = "phone_lookup";
53b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
54b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA = "data";
55b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
56b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA_JOIN_MIMETYPE = "data "
57b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + "LEFT OUTER JOIN mimetype ON (data.mimetype_id = mimetype._id)";
58b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
59b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA_JOIN_PACKAGE_MIMETYPE = "data "
60e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey                + "LEFT OUTER JOIN package ON (data.package_id = package._id) "
61b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + "LEFT OUTER JOIN mimetype ON (data.mimetype_id = mimetype._id)";
62b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
63b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA_JOIN_AGGREGATES_PACKAGE_MIMETYPE = "data "
64e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey                + "LEFT OUTER JOIN package ON (data.package_id = package._id) "
65e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey                + "LEFT OUTER JOIN mimetype ON (data.mimetype_id = mimetype._id) "
66b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + "LEFT JOIN contacts ON (data.contact_id = contacts._id) "
67b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + "LEFT JOIN aggregates ON (contacts.aggregate_id = aggregates._id)";
68b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
69b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String ACTIVITIES = "activities";
70b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
71b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String ACTIVITIES_JOIN_MIMETYPE = "activities "
72499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                + "LEFT OUTER JOIN mimetype ON (activities.mimetype_id = mimetype._id)";
73b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
74b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String ACTIVITIES_JOIN_PACKAGE_MIMETYPE = "activities "
75499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                + "LEFT OUTER JOIN package ON (activities.package_id = package._id) "
76499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                + "LEFT OUTER JOIN mimetype ON (activities.mimetype_id = mimetype._id)";
77e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey
78e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey        public static final String ACTIVITIES_JOIN_AGGREGATES_PACKAGE_MIMETYPE = "activities "
79499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                + "LEFT OUTER JOIN package ON (activities.package_id = package._id) "
80499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                + "LEFT OUTER JOIN mimetype ON (activities.mimetype_id = mimetype._id) "
81499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                + "LEFT JOIN contacts ON (activities.author_contact_id = contacts._id) "
82499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                + "LEFT JOIN aggregates ON (contacts.aggregate_id = aggregates._id)";
83b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
84b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
85b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
86b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface ContactsColumns {
87b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String AGGREGATION_NEEDED = "aggregation_needed";
88b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
89b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
90b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface DataColumns {
91b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PACKAGE_ID = "package_id";
92b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE_ID = "mimetype_id";
93b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
94b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
95b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface ActivitiesColumns {
96b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PACKAGE_ID = "package_id";
97b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE_ID = "mimetype_id";
98b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
99b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
100b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public interface PhoneLookupColumns {
101b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
102b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String DATA_ID = "data_id";
103b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String CONTACT_ID = "contact_id";
104b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String NORMALIZED_NUMBER = "normalized_number";
105b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
106b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
107b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private interface PackageColumns {
108b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
109b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String PACKAGE = "package";
110b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
111b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
112b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private interface MimetypeColumns {
113b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String _ID = BaseColumns._ID;
114b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        public static final String MIMETYPE = "mimetype";
115b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
116b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
117b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
118b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
119b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** In-memory cache of previously found mimetype mappings */
120b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private HashMap<String, Long> mMimetypeCache = new HashMap<String, Long>();
121b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** In-memory cache of previously found package name mappings */
122b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private HashMap<String, Long> mPackageCache = new HashMap<String, Long>();
123b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
124b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
125b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /** Compiled statements for querying and inserting mappings */
126b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mMimetypeQuery;
127b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mPackageQuery;
128b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mMimetypeInsert;
129b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mPackageInsert;
130b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
131b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mDataMimetypeQuery;
132b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private SQLiteStatement mActivitiesMimetypeQuery;
133b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
134b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private static OpenHelper sSingleton = null;
135b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
136b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public static synchronized OpenHelper getInstance(Context context) {
137b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (sSingleton == null) {
138b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            sSingleton = new OpenHelper(context);
139b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
140b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return sSingleton;
141b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
142b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
143b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private OpenHelper(Context context) {
144b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        super(context, DATABASE_NAME, null, DATABASE_VERSION);
145b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        Log.i(TAG, "Creating OpenHelper");
146b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
147b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
148b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
149b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
150b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
151b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onOpen(SQLiteDatabase db) {
152b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Create compiled statements for package and mimetype lookups
153b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        mMimetypeQuery = db.compileStatement("SELECT " + MimetypeColumns._ID + " FROM "
154b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + Tables.MIMETYPE + " WHERE " + MimetypeColumns.MIMETYPE + "=?");
155b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        mPackageQuery = db.compileStatement("SELECT " + PackageColumns._ID + " FROM "
156b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + Tables.PACKAGE + " WHERE " + PackageColumns.PACKAGE + "=?");
157b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        mMimetypeInsert = db.compileStatement("INSERT INTO " + Tables.MIMETYPE + "("
158b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + MimetypeColumns.MIMETYPE + ") VALUES (?)");
159b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        mPackageInsert = db.compileStatement("INSERT INTO " + Tables.PACKAGE + "("
160b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + PackageColumns.PACKAGE + ") VALUES (?)");
161b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
162b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        mDataMimetypeQuery = db.compileStatement("SELECT " + MimetypeColumns.MIMETYPE + " FROM "
163b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + Tables.DATA_JOIN_MIMETYPE + " WHERE " + Tables.DATA + "." + Data._ID + "=?");
164b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        mActivitiesMimetypeQuery = db.compileStatement("SELECT " + MimetypeColumns.MIMETYPE
165b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + " FROM " + Tables.ACTIVITIES_JOIN_MIMETYPE + " WHERE " + Tables.ACTIVITIES + "."
166b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + Activities._ID + "=?");
167b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
168b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
169b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
170b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onCreate(SQLiteDatabase db) {
171b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        Log.i(TAG, "Bootstrapping database");
172b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
173b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // One row per group of contacts corresponding to the same person
174b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.AGGREGATES + " (" +
175b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
176b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Aggregates.DISPLAY_NAME + " TEXT," +
177b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Aggregates.TIMES_CONTACTED + " INTEGER," +
178b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Aggregates.LAST_TIME_CONTACTED + " INTEGER," +
179b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Aggregates.STARRED + " INTEGER" +
180b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
181b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
182b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Contacts table
183b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.CONTACTS + " (" +
184b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Contacts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
185b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Contacts.AGGREGATE_ID + " INTEGER, " +
186b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                ContactsColumns.AGGREGATION_NEEDED + " INTEGER," +
187b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Contacts.CUSTOM_RINGTONE + " TEXT," +
188b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Contacts.SEND_TO_VOICEMAIL + " INTEGER" +
189b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
190b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
191b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Package name mapping table
192b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PACKAGE + " (" +
193b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PackageColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
194b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PackageColumns.PACKAGE + " TEXT" +
195b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
196b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
197b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Mime-type mapping table
198b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.MIMETYPE + " (" +
199b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                MimetypeColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
200b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                MimetypeColumns.MIMETYPE + " TEXT" +
201b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
202b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
203b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Public generic data table
204b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.DATA + " (" +
205b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
206b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                DataColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id) NOT NULL," +
207b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                DataColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
208b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data.CONTACT_ID + " INTEGER NOT NULL," +
209b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data.DATA1 + " NUMERIC," +
210b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data.DATA2 + " NUMERIC," +
211b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data.DATA3 + " NUMERIC," +
212b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data.DATA4 + " NUMERIC," +
213b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data.DATA5 + " NUMERIC," +
214b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data.DATA6 + " NUMERIC," +
215b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data.DATA7 + " NUMERIC," +
216b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data.DATA8 + " NUMERIC," +
217b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data.DATA9 + " NUMERIC," +
218b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Data.DATA10 + " NUMERIC" +
219b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
220b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
221b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Private phone numbers table used for lookup
222b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.PHONE_LOOKUP + " (" +
223b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns._ID + " INTEGER PRIMARY KEY," +
224b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.DATA_ID + " INTEGER REFERENCES data(_id) NOT NULL," +
225b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.CONTACT_ID + " INTEGER REFERENCES contacts(_id) NOT NULL," +
226b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL" +
227b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
228b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
229b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" +
230b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.NORMALIZED_NUMBER + " ASC, " +
231b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.CONTACT_ID + ", " +
232b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                PhoneLookupColumns.DATA_ID +
233b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
234b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
235b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Activities table
236b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("CREATE TABLE " + Tables.ACTIVITIES + " (" +
237b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
238b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                ActivitiesColumns.PACKAGE_ID + " INTEGER REFERENCES package(_id) NOT NULL," +
239b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                ActivitiesColumns.MIMETYPE_ID + " INTEGER REFERENCES mimetype(_id) NOT NULL," +
240b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.RAW_ID + " TEXT," +
241499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.IN_REPLY_TO + " TEXT," +
242b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.AUTHOR_CONTACT_ID +  " INTEGER REFERENCES contacts(_id)," +
243b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.TARGET_CONTACT_ID + " INTEGER REFERENCES contacts(_id)," +
244b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.PUBLISHED + " INTEGER NOT NULL," +
245499791a4f9ab29fa94ff48dd7acff55b2ac089a7Dmitri Plotnikov                Activities.THREAD_PUBLISHED + " INTEGER NOT NULL," +
246b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.TITLE + " TEXT NOT NULL," +
247b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.SUMMARY + " TEXT," +
248adb55c2d8295d300961d86a3605c8ddc469cd4a2Dmitri Plotnikov                Activities.LINK + " TEXT, " +
249b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                Activities.THUMBNAIL + " BLOB" +
250b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        ");");
251b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
252b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
253b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
254b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    @Override
255b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
256b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        Log.i(TAG, "Upgraing from version " + oldVersion + " to " + newVersion
257b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                + ", data will be lost!");
258b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
259b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("DROP TABLE IF EXISTS " + Tables.AGGREGATES + ";");
260b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("DROP TABLE IF EXISTS " + Tables.CONTACTS + ";");
261b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("DROP TABLE IF EXISTS " + Tables.PACKAGE + ";");
262b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("DROP TABLE IF EXISTS " + Tables.MIMETYPE + ";");
263b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("DROP TABLE IF EXISTS " + Tables.DATA + ";");
264b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("DROP TABLE IF EXISTS " + Tables.PHONE_LOOKUP + ";");
265b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        db.execSQL("DROP TABLE IF EXISTS " + Tables.ACTIVITIES + ";");
266b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
267b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        onCreate(db);
268b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
269b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
270b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
271b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
272b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Perform an internal string-to-integer lookup using the compiled
273b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * {@link SQLiteStatement} provided, using the in-memory cache to speed up
274b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups. If a mapping isn't found in cache or database, it will be
275b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * created. All new, uncached answers are added to the cache automatically.
276b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *
277b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param query Compiled statement used to query for the mapping.
278b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param insert Compiled statement used to insert a new mapping when no
279b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     *            existing one is found in cache or from query.
280b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param value Value to find mapping for.
281b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @param cache In-memory cache of previous answers.
282b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * @return An unique integer mapping for the given value.
283b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
284b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    private synchronized long getCachedId(SQLiteStatement query, SQLiteStatement insert,
285b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String value, HashMap<String, Long> cache) {
286b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Try an in-memory cache lookup
287b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (cache.containsKey(value)) {
288b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return cache.get(value);
289b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
290b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
291b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        long id = -1;
292b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
293b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try searching database for mapping
294b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(query, 1, value);
295b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            id = query.simpleQueryForLong();
296b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
297b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Nothing found, so try inserting new mapping
298b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(insert, 1, value);
299b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            id = insert.executeInsert();
300b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
301b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
302b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        if (id != -1) {
303b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Cache and return the new answer
304b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            cache.put(value, id);
305b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return id;
306b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } else {
307b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Otherwise throw if no mapping found or created
308b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            throw new IllegalStateException("Couldn't find or create internal "
309b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey                    + "lookup table entry for value " + value);
310b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
311b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
312b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
313b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
314b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Convert a package name into an integer, using {@link Tables#PACKAGE} for
315b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
316b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
317b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getPackageId(String packageName) {
318b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
319b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
320b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return getCachedId(mPackageQuery, mPackageInsert, packageName, mPackageCache);
321b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
322b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
323b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
324b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Convert a mime-type into an integer, using {@link Tables#MIMETYPE} for
325b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * lookups and possible allocation of new IDs as needed.
326b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
327b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public long getMimeTypeId(String mimetype) {
328b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
329b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
330b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        return getCachedId(mMimetypeQuery, mMimetypeInsert, mimetype, mMimetypeCache);
331b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
332b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
333b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
334b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Find the mime-type for the given {@link Data#_ID}.
335b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
336b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getDataMimeType(long dataId) {
337b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
338b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
339b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
340b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
341b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mDataMimetypeQuery, 1, dataId);
342b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mDataMimetypeQuery.simpleQueryForString();
343b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
344b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
345b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
346b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
347b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
348b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
349b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey
350b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    /**
351b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     * Find the mime-type for the given {@link Activities#_ID}.
352b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey     */
353b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    public String getActivityMimeType(long activityId) {
354b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        // Make sure compiled statements are ready by opening database
355b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        getReadableDatabase();
356b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        try {
357b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // Try database query to find mimetype
358b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            DatabaseUtils.bindObjectToProgram(mActivitiesMimetypeQuery, 1, activityId);
359b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            String mimetype = mActivitiesMimetypeQuery.simpleQueryForString();
360b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return mimetype;
361b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        } catch (SQLiteDoneException e) {
362b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            // No valid mapping found, so return null
363b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey            return null;
364b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey        }
365b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey    }
366b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey}
367