Add calendar database upgrade code.
This switches the CalendarProvider2 code to use the calendar.db database
and upgrade it in place. The upgrade code from versions 57 and 58 is
copied from CalendarProvider.
diff --git a/src/com/android/providers/calendar/CalendarDatabaseHelper.java b/src/com/android/providers/calendar/CalendarDatabaseHelper.java
index ffbb069..0d7bf70 100644
--- a/src/com/android/providers/calendar/CalendarDatabaseHelper.java
+++ b/src/com/android/providers/calendar/CalendarDatabaseHelper.java
@@ -38,7 +38,7 @@
/* package */ class CalendarDatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "CalendarDatabaseHelper";
- private static final String DATABASE_NAME = "calendar2.db";
+ private static final String DATABASE_NAME = "calendar.db";
// TODO: change the Calendar contract so these are defined there.
static final String ACCOUNT_NAME = "_sync_account";
@@ -46,7 +46,7 @@
// Note: if you update the version number, you must also update the code
// in upgradeDatabase() to modify the database (gracefully, if possible).
- private static final int DATABASE_VERSION = 57;
+ private static final int DATABASE_VERSION = 60;
private final Context mContext;
private final SyncStateContentProviderHelper mSyncState;
@@ -340,231 +340,298 @@
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i(TAG, "Upgrading DB from version " + oldVersion
+ " to " + newVersion);
- if (oldVersion < 46) {
+ if (oldVersion < 49) {
dropTables(db);
mSyncState.createDatabase(db);
return; // this was lossy
}
- if (oldVersion == 46) {
- Log.w(TAG, "Upgrading CalendarAlerts table");
- db.execSQL("UPDATE CalendarAlerts SET reminder_id=NULL;");
- db.execSQL("ALTER TABLE CalendarAlerts ADD COLUMN minutes INTEGER DEFAULT 0;");
- oldVersion += 1;
+ if (oldVersion < 51) {
+ upgradeToVersion51(db); // From 50 or 51
+ oldVersion = 51;
}
-
- if (oldVersion == 47) {
- // Changing to version 48 was intended to force a data wipe
- dropTables(db);
- mSyncState.createDatabase(db);
- return; // this was lossy
- }
-
- if (oldVersion == 48) {
- // Changing to version 49 was intended to force a data wipe
- dropTables(db);
- mSyncState.createDatabase(db);
- return; // this was lossy
- }
-
- if (oldVersion == 49) {
- Log.w(TAG, "Upgrading DeletedEvents table");
-
- // We don't have enough information to fill in the correct
- // value of the calendar_id for old rows in the DeletedEvents
- // table, but rows in that table are transient so it is unlikely
- // that there are any rows. Plus, the calendar_id is used only
- // when deleting a calendar, which is a rare event. All new rows
- // will have the correct calendar_id.
- db.execSQL("ALTER TABLE DeletedEvents ADD COLUMN calendar_id INTEGER;");
-
- // Trigger to remove a calendar's events when we delete the calendar
- db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
- db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON Calendars " +
- "BEGIN " +
- "DELETE FROM Events WHERE calendar_id = old._id;" +
- "DELETE FROM DeletedEvents WHERE calendar_id = old._id;" +
- "END");
- db.execSQL("DROP TRIGGER IF EXISTS event_to_deleted");
- oldVersion += 1;
- }
-
- if (oldVersion == 50) {
- // This should have been deleted in the upgrade from version 49
- // but we missed it.
- db.execSQL("DROP TRIGGER IF EXISTS event_to_deleted");
- oldVersion += 1;
- }
-
if (oldVersion == 51) {
- // We added "originalAllDay" to the Events table to keep track of
- // the allDay status of the original recurring event for entries
- // that are exceptions to that recurring event. We need this so
- // that we can format the date correctly for the "originalInstanceTime"
- // column when we make a change to the recurrence exception and
- // send it to the server.
- db.execSQL("ALTER TABLE Events ADD COLUMN originalAllDay INTEGER;");
-
- // Iterate through the Events table and for each recurrence
- // exception, fill in the correct value for "originalAllDay",
- // if possible. The only times where this might not be possible
- // are (1) the original recurring event no longer exists, or
- // (2) the original recurring event does not yet have a _sync_id
- // because it was created on the phone and hasn't been synced to the
- // server yet. In both cases the originalAllDay field will be set
- // to null. In the first case we don't care because the recurrence
- // exception will not be displayed and we won't be able to make
- // any changes to it (and even if we did, the server should ignore
- // them, right?). In the second case, the calendar client already
- // disallows making changes to an instance of a recurring event
- // until the recurring event has been synced to the server so the
- // second case should never occur.
-
- // "cursor" iterates over all the recurrences exceptions.
- Cursor cursor = db.rawQuery("SELECT _id,originalEvent FROM Events"
- + " WHERE originalEvent IS NOT NULL", null /* selection args */);
- if (cursor != null) {
- try {
- while (cursor.moveToNext()) {
- long id = cursor.getLong(0);
- String originalEvent = cursor.getString(1);
-
- // Find the original recurring event (if it exists)
- Cursor recur = db.rawQuery("SELECT allDay FROM Events"
- + " WHERE _sync_id=?", new String[] {originalEvent});
- if (recur == null) {
- continue;
- }
-
- try {
- // Fill in the "originalAllDay" field of the
- // recurrence exception with the "allDay" value
- // from the recurring event.
- if (recur.moveToNext()) {
- int allDay = recur.getInt(0);
- db.execSQL("UPDATE Events SET originalAllDay=" + allDay
- + " WHERE _id="+id);
- }
- } finally {
- recur.close();
- }
- }
- } finally {
- cursor.close();
- }
- }
+ upgradeToVersion52(db);
oldVersion += 1;
}
-
if (oldVersion == 52) {
- Log.w(TAG, "Upgrading CalendarAlerts table");
- db.execSQL("ALTER TABLE CalendarAlerts ADD COLUMN creationTime INTEGER DEFAULT 0;");
- db.execSQL("ALTER TABLE CalendarAlerts ADD COLUMN receivedTime INTEGER DEFAULT 0;");
- db.execSQL("ALTER TABLE CalendarAlerts ADD COLUMN notifyTime INTEGER DEFAULT 0;");
+ upgradeToVersion53(db);
oldVersion += 1;
}
-
if (oldVersion == 53) {
- Log.w(TAG, "adding eventSyncAccountAndIdIndex");
- db.execSQL("CREATE INDEX eventSyncAccountAndIdIndex ON Events ("
- + Calendar.Events._SYNC_ACCOUNT + ", " + Calendar.Events._SYNC_ID + ");");
+ upgradeToVersion54(db);
oldVersion += 1;
}
-
if (oldVersion == 54) {
- db.execSQL("ALTER TABLE Calendars ADD COLUMN _sync_account_type TEXT;");
- db.execSQL("ALTER TABLE Events ADD COLUMN _sync_account_type TEXT;");
- db.execSQL("ALTER TABLE DeletedEvents ADD COLUMN _sync_account_type TEXT;");
- db.execSQL("UPDATE Calendars"
- + " SET _sync_account_type='com.google'"
- + " WHERE _sync_account IS NOT NULL");
- db.execSQL("UPDATE Events"
- + " SET _sync_account_type='com.google'"
- + " WHERE _sync_account IS NOT NULL");
- db.execSQL("UPDATE DeletedEvents"
- + " SET _sync_account_type='com.google'"
- + " WHERE _sync_account IS NOT NULL");
- Log.w(TAG, "re-creating eventSyncAccountAndIdIndex");
- db.execSQL("DROP INDEX eventSyncAccountAndIdIndex");
- db.execSQL("CREATE INDEX eventSyncAccountAndIdIndex ON Events ("
- + Calendar.Events._SYNC_ACCOUNT_TYPE + ", "
- + Calendar.Events._SYNC_ACCOUNT + ", "
- + Calendar.Events._SYNC_ID + ");");
+ upgradeToVersion55(db);
oldVersion += 1;
}
- if (oldVersion == 55 || oldVersion == 56) { // Both require resync
- // Delete sync state, so all records will be re-synced.
- db.execSQL("DELETE FROM _sync_state;");
-
- // "cursor" iterates over all the calendars
- Cursor cursor = db.rawQuery("SELECT _sync_account,_sync_account_type,url "
- + "FROM Calendars",
- null /* selection args */);
- if (cursor != null) {
- try {
- while (cursor.moveToNext()) {
- String accountName = cursor.getString(0);
- String accountType = cursor.getString(1);
- final Account account = new Account(accountName, accountType);
- String calendarUrl = cursor.getString(2);
- scheduleSync(account, false /* two-way sync */, calendarUrl);
- }
- } finally {
- cursor.close();
- }
- }
+ if (oldVersion == 55 || oldVersion == 56) {
+ // Both require resync, so just schedule it once
+ upgradeResync(db);
}
if (oldVersion == 55) {
- db.execSQL("ALTER TABLE Calendars ADD COLUMN ownerAccount TEXT;");
- db.execSQL("ALTER TABLE Events ADD COLUMN hasAttendeeData INTEGER;");
- // Clear _sync_dirty to avoid a client-to-server sync that could blow away
- // server attendees.
- // Clear _sync_version to pull down the server's event (with attendees)
- // Change the URLs from full-selfattendance to full
- db.execSQL("UPDATE Events"
- + " SET _sync_dirty=0,"
- + " _sync_version=NULL,"
- + " _sync_id="
- + "REPLACE(_sync_id, '/private/full-selfattendance', '/private/full'),"
- + " commentsUri ="
- + "REPLACE(commentsUri, '/private/full-selfattendance', '/private/full');");
- db.execSQL("UPDATE Calendars"
- + " SET url="
- + "REPLACE(url, '/private/full-selfattendance', '/private/full');");
-
- // "cursor" iterates over all the calendars
- Cursor cursor = db.rawQuery("SELECT _id, url FROM Calendars",
- null /* selection args */);
- // Add the owner column.
- if (cursor != null) {
- try {
- while (cursor.moveToNext()) {
- Long id = cursor.getLong(0);
- String url = cursor.getString(1);
- String owner = CalendarSyncAdapter.calendarEmailAddressFromFeedUrl(url);
- db.execSQL("UPDATE Calendars SET ownerAccount=? WHERE _id=?",
- new Object[] {owner, id});
- }
- } finally {
- cursor.close();
- }
- }
+ upgradeToVersion56(db);
oldVersion += 1;
}
if (oldVersion == 56) {
- db.execSQL("ALTER TABLE Events ADD COLUMN guestsCanModify"
- + " INTEGER NOT NULL DEFAULT 0;");
- db.execSQL("ALTER TABLE Events ADD COLUMN guestsCanInviteOthers"
- + " INTEGER NOT NULL DEFAULT 1;");
- db.execSQL("ALTER TABLE Events ADD COLUMN guestsCanSeeGuests"
- + " INTEGER NOT NULL DEFAULT 1;");
- db.execSQL("ALTER TABLE Events ADD COLUMN organizer STRING;");
- db.execSQL("UPDATE Events SET organizer="
- + "(SELECT attendeeEmail FROM Attendees WHERE "
- + "Attendees.event_id = Events._id"
- + " AND Attendees.attendeeRelationship=2);");
+ upgradeToVersion57(db);
oldVersion += 1;
}
+ if (oldVersion == 57) {
+ // Changes are undone upgrading to 60, so don't do anything.
+ oldVersion += 1;
+ }
+ if (oldVersion == 58) {
+ upgradeToVersion59(db);
+ oldVersion += 1;
+ }
+ if (oldVersion == 59) {
+ upgradeToVersion60(db);
+ oldVersion += 1;
+ }
+ }
+
+ private void upgradeToVersion56(SQLiteDatabase db) {
+ db.execSQL("ALTER TABLE Calendars ADD COLUMN ownerAccount TEXT;");
+ db.execSQL("ALTER TABLE Events ADD COLUMN hasAttendeeData INTEGER;");
+ // Clear _sync_dirty to avoid a client-to-server sync that could blow away
+ // server attendees.
+ // Clear _sync_version to pull down the server's event (with attendees)
+ // Change the URLs from full-selfattendance to full
+ db.execSQL("UPDATE Events"
+ + " SET _sync_dirty=0,"
+ + " _sync_version=NULL,"
+ + " _sync_id="
+ + "REPLACE(_sync_id, '/private/full-selfattendance', '/private/full'),"
+ + " commentsUri ="
+ + "REPLACE(commentsUri, '/private/full-selfattendance', '/private/full');");
+ db.execSQL("UPDATE Calendars"
+ + " SET url="
+ + "REPLACE(url, '/private/full-selfattendance', '/private/full');");
+
+ // "cursor" iterates over all the calendars
+ Cursor cursor = db.rawQuery("SELECT _id, url FROM Calendars",
+ null /* selection args */);
+ // Add the owner column.
+ if (cursor != null) {
+ try {
+ while (cursor.moveToNext()) {
+ Long id = cursor.getLong(0);
+ String url = cursor.getString(1);
+ String owner = CalendarSyncAdapter.calendarEmailAddressFromFeedUrl(url);
+ db.execSQL("UPDATE Calendars SET ownerAccount=? WHERE _id=?",
+ new Object[] {owner, id});
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+
+ private void upgradeResync(SQLiteDatabase db) {
+ // Delete sync state, so all records will be re-synced.
+ db.execSQL("DELETE FROM _sync_state;");
+
+ // "cursor" iterates over all the calendars
+ Cursor cursor = db.rawQuery("SELECT _sync_account,_sync_account_type,url "
+ + "FROM Calendars",
+ null /* selection args */);
+ if (cursor != null) {
+ try {
+ while (cursor.moveToNext()) {
+ String accountName = cursor.getString(0);
+ String accountType = cursor.getString(1);
+ final Account account = new Account(accountName, accountType);
+ String calendarUrl = cursor.getString(2);
+ scheduleSync(account, false /* two-way sync */, calendarUrl);
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+
+ private void upgradeToVersion60(SQLiteDatabase db) {
+ // Switch to CalendarProvider2
+ db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
+ db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON Calendars " +
+ "BEGIN " +
+ "DELETE FROM Events WHERE calendar_id = old._id;" +
+ "END");
+ db.execSQL("ALTER TABLE Events ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0;");
+ db.execSQL("DROP TRIGGER IF EXISTS events_insert");
+ db.execSQL("CREATE TRIGGER events_insert AFTER INSERT ON Events " +
+ "BEGIN " +
+ "UPDATE Events SET _sync_account=" +
+ "(SELECT _sync_account FROM Calendars WHERE Calendars._id=new.calendar_id)," +
+ "_sync_account_type=" +
+ "(SELECT _sync_account_type FROM Calendars WHERE Calendars._id=new.calendar_id) " +
+ "WHERE Events._id=new._id;" +
+ "END");
+ db.execSQL("DROP TABLE IF EXISTS DeletedEvents;");
+ db.execSQL("DROP TRIGGER IF EXISTS events_cleanup_delete");
+ db.execSQL("CREATE TRIGGER events_cleanup_delete DELETE ON Events " +
+ "BEGIN " +
+ "DELETE FROM Instances WHERE event_id = old._id;" +
+ "DELETE FROM EventsRawTimes WHERE event_id = old._id;" +
+ "DELETE FROM Attendees WHERE event_id = old._id;" +
+ "DELETE FROM Reminders WHERE event_id = old._id;" +
+ "DELETE FROM CalendarAlerts WHERE event_id = old._id;" +
+ "DELETE FROM ExtendedProperties WHERE event_id = old._id;" +
+ "END");
+ db.execSQL("DROP TRIGGER IF EXISTS attendees_update");
+ db.execSQL("DROP TRIGGER IF EXISTS attendees_insert");
+ db.execSQL("DROP TRIGGER IF EXISTS attendees_delete");
+ db.execSQL("DROP TRIGGER IF EXISTS reminders_update");
+ db.execSQL("DROP TRIGGER IF EXISTS reminders_insert");
+ db.execSQL("DROP TRIGGER IF EXISTS reminders_delete");
+ db.execSQL("DROP TRIGGER IF EXISTS extended_properties_update");
+ db.execSQL("DROP TRIGGER IF EXISTS extended_properties_insert");
+ db.execSQL("DROP TRIGGER IF EXISTS extended_properties_delete");
+
+ createEventsView(db);
+ }
+
+ private void upgradeToVersion59(SQLiteDatabase db) {
+ db.execSQL("DROP TABLE IF EXISTS BusyBits;");
+ db.execSQL("CREATE TEMPORARY TABLE CalendarMetaData_Backup" +
+ "(_id,localTimezone,minInstance,maxInstance);");
+ db.execSQL("INSERT INTO CalendarMetaData_Backup " +
+ "SELECT _id,localTimezone,minInstance,maxInstance FROM CalendarMetaData;");
+ db.execSQL("DROP TABLE CalendarMetaData;");
+ db.execSQL("CREATE TABLE CalendarMetaData(_id,localTimezone,minInstance,maxInstance);");
+ db.execSQL("INSERT INTO CalendarMetaData " +
+ "SELECT _id,localTimezone,minInstance,maxInstance FROM CalendarMetaData_Backup;");
+ db.execSQL("DROP TABLE CalendarMetaData_Backup;");
+ }
+
+ private void upgradeToVersion57(SQLiteDatabase db) {
+ db.execSQL("ALTER TABLE Events ADD COLUMN guestsCanModify"
+ + " INTEGER NOT NULL DEFAULT 0;");
+ db.execSQL("ALTER TABLE Events ADD COLUMN guestsCanInviteOthers"
+ + " INTEGER NOT NULL DEFAULT 1;");
+ db.execSQL("ALTER TABLE Events ADD COLUMN guestsCanSeeGuests"
+ + " INTEGER NOT NULL DEFAULT 1;");
+ db.execSQL("ALTER TABLE Events ADD COLUMN organizer STRING;");
+ db.execSQL("UPDATE Events SET organizer="
+ + "(SELECT attendeeEmail FROM Attendees WHERE "
+ + "Attendees.event_id = Events._id"
+ + " AND Attendees.attendeeRelationship=2);");
+ }
+
+ private void upgradeToVersion55(SQLiteDatabase db) {
+ db.execSQL("ALTER TABLE Calendars ADD COLUMN _sync_account_type TEXT;");
+ db.execSQL("ALTER TABLE Events ADD COLUMN _sync_account_type TEXT;");
+ db.execSQL("ALTER TABLE DeletedEvents ADD COLUMN _sync_account_type TEXT;");
+ db.execSQL("UPDATE Calendars"
+ + " SET _sync_account_type='com.google'"
+ + " WHERE _sync_account IS NOT NULL");
+ db.execSQL("UPDATE Events"
+ + " SET _sync_account_type='com.google'"
+ + " WHERE _sync_account IS NOT NULL");
+ db.execSQL("UPDATE DeletedEvents"
+ + " SET _sync_account_type='com.google'"
+ + " WHERE _sync_account IS NOT NULL");
+ Log.w(TAG, "re-creating eventSyncAccountAndIdIndex");
+ db.execSQL("DROP INDEX eventSyncAccountAndIdIndex");
+ db.execSQL("CREATE INDEX eventSyncAccountAndIdIndex ON Events ("
+ + Calendar.Events._SYNC_ACCOUNT_TYPE + ", "
+ + Calendar.Events._SYNC_ACCOUNT + ", "
+ + Calendar.Events._SYNC_ID + ");");
+ }
+
+ private void upgradeToVersion54(SQLiteDatabase db) {
+ Log.w(TAG, "adding eventSyncAccountAndIdIndex");
+ db.execSQL("CREATE INDEX eventSyncAccountAndIdIndex ON Events ("
+ + Calendar.Events._SYNC_ACCOUNT + ", " + Calendar.Events._SYNC_ID + ");");
+ }
+
+ private void upgradeToVersion53(SQLiteDatabase db) {
+ Log.w(TAG, "Upgrading CalendarAlerts table");
+ db.execSQL("ALTER TABLE CalendarAlerts ADD COLUMN creationTime INTEGER DEFAULT 0;");
+ db.execSQL("ALTER TABLE CalendarAlerts ADD COLUMN receivedTime INTEGER DEFAULT 0;");
+ db.execSQL("ALTER TABLE CalendarAlerts ADD COLUMN notifyTime INTEGER DEFAULT 0;");
+ }
+
+ private void upgradeToVersion52(SQLiteDatabase db) {
+ // We added "originalAllDay" to the Events table to keep track of
+ // the allDay status of the original recurring event for entries
+ // that are exceptions to that recurring event. We need this so
+ // that we can format the date correctly for the "originalInstanceTime"
+ // column when we make a change to the recurrence exception and
+ // send it to the server.
+ db.execSQL("ALTER TABLE Events ADD COLUMN originalAllDay INTEGER;");
+
+ // Iterate through the Events table and for each recurrence
+ // exception, fill in the correct value for "originalAllDay",
+ // if possible. The only times where this might not be possible
+ // are (1) the original recurring event no longer exists, or
+ // (2) the original recurring event does not yet have a _sync_id
+ // because it was created on the phone and hasn't been synced to the
+ // server yet. In both cases the originalAllDay field will be set
+ // to null. In the first case we don't care because the recurrence
+ // exception will not be displayed and we won't be able to make
+ // any changes to it (and even if we did, the server should ignore
+ // them, right?). In the second case, the calendar client already
+ // disallows making changes to an instance of a recurring event
+ // until the recurring event has been synced to the server so the
+ // second case should never occur.
+
+ // "cursor" iterates over all the recurrences exceptions.
+ Cursor cursor = db.rawQuery("SELECT _id,originalEvent FROM Events"
+ + " WHERE originalEvent IS NOT NULL", null /* selection args */);
+ if (cursor != null) {
+ try {
+ while (cursor.moveToNext()) {
+ long id = cursor.getLong(0);
+ String originalEvent = cursor.getString(1);
+
+ // Find the original recurring event (if it exists)
+ Cursor recur = db.rawQuery("SELECT allDay FROM Events"
+ + " WHERE _sync_id=?", new String[] {originalEvent});
+ if (recur == null) {
+ continue;
+ }
+
+ try {
+ // Fill in the "originalAllDay" field of the
+ // recurrence exception with the "allDay" value
+ // from the recurring event.
+ if (recur.moveToNext()) {
+ int allDay = recur.getInt(0);
+ db.execSQL("UPDATE Events SET originalAllDay=" + allDay
+ + " WHERE _id="+id);
+ }
+ } finally {
+ recur.close();
+ }
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+
+ private void upgradeToVersion51(SQLiteDatabase db) {
+ Log.w(TAG, "Upgrading DeletedEvents table");
+
+ // We don't have enough information to fill in the correct
+ // value of the calendar_id for old rows in the DeletedEvents
+ // table, but rows in that table are transient so it is unlikely
+ // that there are any rows. Plus, the calendar_id is used only
+ // when deleting a calendar, which is a rare event. All new rows
+ // will have the correct calendar_id.
+ db.execSQL("ALTER TABLE DeletedEvents ADD COLUMN calendar_id INTEGER;");
+
+ // Trigger to remove a calendar's events when we delete the calendar
+ db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
+ db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON Calendars " +
+ "BEGIN " +
+ "DELETE FROM Events WHERE calendar_id = old._id;" +
+ "DELETE FROM DeletedEvents WHERE calendar_id = old._id;" +
+ "END");
+ db.execSQL("DROP TRIGGER IF EXISTS event_to_deleted");
}
private void dropTables(SQLiteDatabase db) {